package com.genexususa.eo.google.connection;

import com.genexususa.eo.google.data.*;
import com.google.api.ads.adwords.axis.v201409.cm.*;
import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathFactory;
import java.io.PrintWriter;
import java.io.StringReader;
import java.io.StringWriter;
import java.rmi.RemoteException;
import java.util.ArrayList;
import java.util.HashMap;

public class CampaignManager {


    private String _clientId;

    public void SetClientId(String clientId) {
        this._clientId = clientId;
    }

    public String GetClientId() {
        return _clientId;
    }

    public void Finalize() {

        SessionController sc = SessionController.getInstance();
        sc.RemoveSession(_clientId);
    }


    private static final int PAGE_SIZE = 5000;

    public String CreateCampaign(String xml) {

        try {
            String result = "";
            GA_Result res = new GA_Result();
            // Get the instance of service's factory
            ServiceFactory sf = ServiceFactory.getInstance();
            Budget toRemove = null;

            HashMap<String, Long> gxIds = new HashMap<String, Long>();
            HashMap<String, Long> budgetGxIds = new HashMap<String, Long>();

            HashMap<Long, Budget> budgetsCreated = new HashMap<Long, Budget>();
            try {
                Document doc = loadXMLFromString(xml);
                XPathFactory factory = XPathFactory.newInstance();
                XPath xpath = factory.newXPath();
                XPathExpression expr
                        = xpath.compile("//Budget");
                Object budgetNodes = expr.evaluate(doc, XPathConstants.NODESET);
                NodeList budgets = (NodeList) budgetNodes;

                if (budgets.getLength() > 0) {
                    for (int i = 0; i < budgets.getLength(); i++) {
                        Node n = budgets.item(i);
                        NodeList children = n.getChildNodes(); // Children of budget node
                        ArrayList<Campaign> campaigns = new ArrayList<Campaign>();
                        for (int j = 0; j < children.getLength(); j++) {
                            Node child = children.item(j);
                            NodeList budgetChildren = child.getChildNodes();
                            if (budgetChildren.getLength() > 0) {
                                for (int h = 0; h < budgetChildren.getLength(); h++) {
                                    if (budgetChildren.item(h).getNodeName().equalsIgnoreCase("SubCampaign")) {
                                        NodeList campaignChildren = budgetChildren.item(h).getChildNodes();
                                        Campaign campaign = new Campaign();
                                        String campaignName = "";
                                        Long gxId = 0L;
                                        for (int z = 0; z < campaignChildren.getLength(); z++) {
                                            Node node = campaignChildren.item(z);
                                            String nodeName = node.getNodeName();

                                            /** Start Campaign Name **/
                                            if (nodeName.equalsIgnoreCase("Name")) {
                                                campaign.setName(campaignChildren.item(z).getTextContent());
                                                campaignName = campaignChildren.item(z).getTextContent();
                                            }
                                            /** End Campaign Name **/

                                            if (nodeName.equalsIgnoreCase("AdvertisingChannelType")) {
                                                if (campaignChildren.item(z).getTextContent() != ""){
                                                    try{
                                                    campaign.setAdvertisingChannelType(AdvertisingChannelType.fromString(campaignChildren.item(z).getTextContent()));
                                                    }catch (Exception e){
                                                        campaign.setAdvertisingChannelType(AdvertisingChannelType.SEARCH);
                                                    }
                                                }else{
                                                    campaign.setAdvertisingChannelType(AdvertisingChannelType.SEARCH);
                                                }
                                            }

                                            if (nodeName.equalsIgnoreCase("SubCampaignGXId")) {
                                                gxId = Long.parseLong(campaignChildren.item(z).getTextContent());
                                            }

                                            /** Start Campaign Status **/

                                            if (nodeName.equalsIgnoreCase("Status")) {
                                                if (node.getTextContent().equalsIgnoreCase("A")) {
                                                    campaign.setStatus(CampaignStatus.ENABLED);
                                                } else if (node.getTextContent().equalsIgnoreCase("P")) {
                                                    campaign.setStatus(CampaignStatus.PAUSED);
                                                } else if (node.getTextContent().equalsIgnoreCase("D")) {
                                                    campaign.setStatus(CampaignStatus.REMOVED);
                                                }
                                            }

                                            /** End Campaign Status **/

                                            /** Start Campaign Serving Status **/

                                            if (nodeName.equalsIgnoreCase("ServingStatus")) {
                                                if (node.getTextContent().equalsIgnoreCase("S")) {
                                                    campaign.setServingStatus(ServingStatus.SERVING);
                                                }
                                                if (node.getTextContent().equalsIgnoreCase("N")) {
                                                    campaign.setServingStatus(ServingStatus.NONE);
                                                }
                                                if (node.getTextContent().equalsIgnoreCase("E")) {
                                                    campaign.setServingStatus(ServingStatus.ENDED);
                                                }
                                                if (node.getTextContent().equalsIgnoreCase("P")) {
                                                    campaign.setServingStatus(ServingStatus.PENDING);
                                                }
                                                if (node.getTextContent().equalsIgnoreCase("SU")) {
                                                    campaign.setServingStatus(ServingStatus.SUSPENDED);
                                                }
                                            }

                                            /** End Campaign Serving Status **/

                                            /** Start Campaign Start Date **/

                                            if (nodeName.equalsIgnoreCase("StartDate")) {
                                                String sd = node.getTextContent();

                                                DateTimeFormatter df = DateTimeFormat.forPattern("yyyy-MM-dd");
                                                DateTime dateTime = df.parseDateTime(sd);

                                                campaign.setStartDate(dateTime.toString("yyyyMMdd"));
                                            }

                                            /** End Campaign Start Date **/

                                            /** Start Campaign End Date **/

                                            if (nodeName.equalsIgnoreCase("EndDate")) {
                                                String ed = node.getTextContent();

                                                try {
                                                    DateTimeFormatter df = DateTimeFormat.forPattern("yyyy-MM-dd");
                                                    DateTime dateTime = df.parseDateTime(ed);

                                                    campaign.setEndDate(dateTime.toString("yyyyMMdd"));

                                                } catch (IllegalArgumentException exc) {

                                                }
                                            }

                                            /** End Campaign End Date **/

                                            //region Bidding Strategies
                                            /** Start Campaign Bidding Strategies **/

                                            if (nodeName.equalsIgnoreCase("BiddingStrategyConfiguration")) {

                                                NodeList biddingStrategyConfiguration = node.getChildNodes();

                                                if (biddingStrategyConfiguration.getLength() > 0) {
                                                    for (int a=0; a<biddingStrategyConfiguration.getLength(); a++) {
                                                        BiddingStrategyConfiguration bsc = new BiddingStrategyConfiguration();
                                                        if (biddingStrategyConfiguration.item(a).getNodeName().equalsIgnoreCase("BiddingScheme")) {

                                                            NodeList strategies = biddingStrategyConfiguration.item(a).getChildNodes();

                                                            if (strategies.getLength() > 0) {

                                                                for (int y = 0; y < strategies.getLength(); y++) {

                                                                    if (strategies.item(y).getNodeName().equalsIgnoreCase("BSConversionOptimizer")) {
                                                                        Node bsConversionOptimizer = strategies.item(y);

                                                                        NodeList bsConversionOptimizerChildren = bsConversionOptimizer.getChildNodes();

                                                                        if (bsConversionOptimizerChildren.getLength() > 0) {

                                                                            ConversionOptimizerBiddingScheme co = new ConversionOptimizerBiddingScheme();

                                                                            for (int index = 0; index < bsConversionOptimizerChildren.getLength(); index++) {

                                                                                if (bsConversionOptimizerChildren.item(index).getNodeName().equalsIgnoreCase("BSConvOptPricingModel")) {
                                                                                    if (bsConversionOptimizerChildren.item(index).getTextContent().equalsIgnoreCase("C")) {
                                                                                        co.setPricingMode(ConversionOptimizerBiddingSchemePricingMode.CLICKS);
                                                                                    } else if (bsConversionOptimizerChildren.item(index).getTextContent().equalsIgnoreCase("CN")) {
                                                                                        co.setPricingMode(ConversionOptimizerBiddingSchemePricingMode.CONVERSIONS);
                                                                                    }
                                                                                }

                                                                                if (bsConversionOptimizerChildren.item(index).getNodeName().equalsIgnoreCase("BSConvOptBidType")) {
                                                                                    if (bsConversionOptimizerChildren.item(index).getTextContent().equalsIgnoreCase("T")) {
                                                                                        co.setBidType(ConversionOptimizerBiddingSchemeBidType.TARGET_CPA);
                                                                                    }
                                                                                }
                                                                            }
                                                                            bsc.setBiddingScheme(co);
                                                                        }

                                                                    }

                                                                    if (strategies.item(y).getNodeName().equalsIgnoreCase("BSManualCPC")) {
                                                                        Node manualCPCNode = strategies.item(y);
                                                                        NodeList manualCPCChildren = manualCPCNode.getChildNodes();
                                                                        ManualCpcBiddingScheme manualCPC = new ManualCpcBiddingScheme();
                                                                        for (int index = 0; index < manualCPCChildren.getLength(); index++) {
                                                                            if (manualCPCChildren.item(index).getNodeName().equalsIgnoreCase("enhancedCpcEnabled")) {
                                                                                if (manualCPCChildren.item(index).getTextContent().equalsIgnoreCase("true")) {
                                                                                    manualCPC.setEnhancedCpcEnabled(true);
                                                                                } else {
                                                                                    manualCPC.setEnhancedCpcEnabled(false);
                                                                                }
                                                                            }
                                                                        }

                                                                        bsc.setBiddingScheme(manualCPC);
                                                                    }

                                                                    if (strategies.item(y).getNodeName().equalsIgnoreCase("BSEnhancedCPC")) {

                                                                        Node enhancedCPCNode = strategies.item(y);
                                                                        NodeList enhancedCPCChildren = enhancedCPCNode.getChildNodes();
                                                                        for (int index = 0; index < enhancedCPCChildren.getLength(); index++) {

                                                                            if (enhancedCPCChildren.item(index).getNodeName().equalsIgnoreCase("BiddingId")){
                                                                                bsc.setBiddingStrategyId(Long.parseLong(enhancedCPCChildren.item(index).getTextContent()));
                                                                            }

                                                                        }
                                                                    }

                                                                    if (strategies.item(y).getNodeName().equalsIgnoreCase("BSManualCPM")) {
                                                                        Node manualCPMNode = strategies.item(y);

                                                                        NodeList manualCPMChildren = manualCPMNode.getChildNodes();

                                                                        for (int index = 0; index < manualCPMChildren.getLength(); index++) {

                                                                            if (manualCPMChildren.item(index).getNodeName().equalsIgnoreCase("enable")) {
                                                                                if (manualCPMChildren.item(index).getTextContent().equalsIgnoreCase("true")) {
                                                                                    bsc.setBiddingScheme(new ManualCpmBiddingScheme());
                                                                                }
                                                                            }
                                                                        }
                                                                    }


                                                                    if (strategies.item(y).getNodeName().equalsIgnoreCase("BSBudgetOptimizer")) {
                                                                        Node bsBudgetOptimizerNode = strategies.item(y);
                                                                        NodeList bsBudgetOptimizerNodeChildren = bsBudgetOptimizerNode.getChildNodes();
                                                                        BudgetOptimizerBiddingScheme bo = new BudgetOptimizerBiddingScheme();
                                                                        for (int index = 0; index < bsBudgetOptimizerNodeChildren.getLength(); index++) {
                                                                            if (bsBudgetOptimizerNodeChildren.item(index).getNodeName().equalsIgnoreCase("enhancedCpcEnabled")) {
                                                                                if (bsBudgetOptimizerNodeChildren.item(index).getTextContent().equalsIgnoreCase("true")) {
                                                                                    bo.setEnhancedCpcEnabled(true);
                                                                                } else {
                                                                                    bo.setEnhancedCpcEnabled(false);
                                                                                }
                                                                            }

                                                                            if (bsBudgetOptimizerNodeChildren.item(index).getNodeName().equalsIgnoreCase("bidCeiling")) {
                                                                                Money bidCeilingMoney = new Money();
                                                                                Double amount = Double.parseDouble(bsBudgetOptimizerNodeChildren.item(index).getTextContent());
                                                                                Long microAmount = (long) (amount * 10000000L / 10);
                                                                                bidCeilingMoney.setMicroAmount(microAmount);
                                                                                bo.setBidCeiling(bidCeilingMoney);
                                                                            }
                                                                        }
                                                                        bsc.setBiddingScheme(bo);
                                                                    }
                                                                }
                                                                campaign.setBiddingStrategyConfiguration(bsc);
                                                            }
                                                        }
                                                    }
                                                }
                                            }

                                            /** End Campaign Bidding Strategies **/
                                            //endregion

                                            /** Start Campaign Ad Serving Optimization Status **/

                                            if (nodeName.equalsIgnoreCase("AdServingOptimizationStatus")) {
                                                if (node.getTextContent().equalsIgnoreCase("O")) {
                                                    campaign.setAdServingOptimizationStatus(AdServingOptimizationStatus.OPTIMIZE);
                                                } else if (node.getTextContent().equalsIgnoreCase("C")) {
                                                    campaign.setAdServingOptimizationStatus(AdServingOptimizationStatus.CONVERSION_OPTIMIZE);
                                                } else if (node.getTextContent().equalsIgnoreCase("R")) {
                                                    campaign.setAdServingOptimizationStatus(AdServingOptimizationStatus.ROTATE);
                                                } else if (node.getTextContent().equalsIgnoreCase("RI")) {
                                                    campaign.setAdServingOptimizationStatus(AdServingOptimizationStatus.ROTATE_INDEFINITELY);
                                                } else if (node.getTextContent().equalsIgnoreCase("U")) {
                                                    campaign.setAdServingOptimizationStatus(AdServingOptimizationStatus.UNAVAILABLE);
                                                }
                                            }

                                            /** End Campaign Ad Serving Optimization Status **/

                                            /** Start Campaign Frequency Cap **/

                                            if (nodeName.equalsIgnoreCase("FrequencyCap")) {

                                                NodeList frequencyCapNodeChildren = node.getChildNodes();

                                                if (frequencyCapNodeChildren.getLength() > 0) {

                                                    FrequencyCap fc = new FrequencyCap();

                                                    for (int index = 0; index < frequencyCapNodeChildren.getLength(); index++) {

                                                        if (frequencyCapNodeChildren.item(index).getNodeName().equalsIgnoreCase("FreqImpressions")) {
                                                            fc.setImpressions(Long.parseLong(frequencyCapNodeChildren.item(index).getTextContent()));
                                                        }

                                                        if (frequencyCapNodeChildren.item(index).getNodeName().equalsIgnoreCase("FreqLevel")) {

                                                            if (frequencyCapNodeChildren.item(index).getTextContent().equalsIgnoreCase("A")) {
                                                                fc.setLevel(Level.ADGROUP);
                                                            } else if (frequencyCapNodeChildren.item(index).getTextContent().equalsIgnoreCase("C")) {
                                                                fc.setLevel(Level.CREATIVE);
                                                            } else if (frequencyCapNodeChildren.item(index).getTextContent().equalsIgnoreCase("CM")) {
                                                                fc.setLevel(Level.CAMPAIGN);
                                                            } else if (frequencyCapNodeChildren.item(index).getTextContent().equalsIgnoreCase("U")) {
                                                                fc.setLevel(Level.UNKNOWN);
                                                            }

                                                        }

                                                        if (frequencyCapNodeChildren.item(index).getNodeName().equalsIgnoreCase("FreqTimeUnit")) {
                                                            if (frequencyCapNodeChildren.item(index).getTextContent().equalsIgnoreCase("M")) {
                                                                fc.setTimeUnit(TimeUnit.MINUTE);
                                                            } else if (frequencyCapNodeChildren.item(index).getTextContent().equalsIgnoreCase("H")) {
                                                                fc.setTimeUnit(TimeUnit.HOUR);
                                                            } else if (frequencyCapNodeChildren.item(index).getTextContent().equalsIgnoreCase("D")) {
                                                                fc.setTimeUnit(TimeUnit.DAY);
                                                            } else if (frequencyCapNodeChildren.item(index).getTextContent().equalsIgnoreCase("W")) {
                                                                fc.setTimeUnit(TimeUnit.WEEK);
                                                            } else if (frequencyCapNodeChildren.item(index).getTextContent().equalsIgnoreCase("MN")) {
                                                                fc.setTimeUnit(TimeUnit.MONTH);
                                                            } else if (frequencyCapNodeChildren.item(index).getTextContent().equalsIgnoreCase("L")) {
                                                                fc.setTimeUnit(TimeUnit.LIFETIME);
                                                            }
                                                        }

                                                    }

                                                    campaign.setFrequencyCap(fc);
                                                }
                                            }

                                            /** End Campaign Frequency Cap **/

                                            /** Start Campaign Settings **/

                                            if (nodeName.equalsIgnoreCase("Settings")) {

                                                NodeList settings = node.getChildNodes();

                                                ArrayList<Setting> settingsList = new ArrayList<Setting>();

                                                if (settings.getLength() > 0) {

                                                    for (int x = 0; x < settings.getLength(); x++) {

                                                        if (settings.item(x).getNodeName().equalsIgnoreCase("GeoTargetTypeSetting")) {

                                                            GeoTargetTypeSetting geoSetting = new GeoTargetTypeSetting();

                                                            NodeList geoTargetChildren = settings.item(x).getChildNodes();

                                                            for (int ch = 0; ch < geoTargetChildren.getLength(); ch++) {

                                                                if (geoTargetChildren.item(ch).getNodeName().equalsIgnoreCase("GeoTargetPositiveType")) {
                                                                    if (geoTargetChildren.item(ch).getTextContent().equalsIgnoreCase("D")) {
                                                                        geoSetting.setPositiveGeoTargetType(GeoTargetTypeSettingPositiveGeoTargetType.DONT_CARE);
                                                                    } else if (geoTargetChildren.item(ch).getTextContent().equalsIgnoreCase("A")) {
                                                                        geoSetting.setPositiveGeoTargetType(GeoTargetTypeSettingPositiveGeoTargetType.AREA_OF_INTEREST);
                                                                    } else if (geoTargetChildren.item(ch).getTextContent().equalsIgnoreCase("l")) {
                                                                        geoSetting.setPositiveGeoTargetType(GeoTargetTypeSettingPositiveGeoTargetType.LOCATION_OF_PRESENCE);
                                                                    }
                                                                }

                                                                if (geoTargetChildren.item(ch).getNodeName().equalsIgnoreCase("GeoTargetNegativeType")) {
                                                                    if (geoTargetChildren.item(ch).getTextContent().equalsIgnoreCase("D")) {
                                                                        geoSetting.setNegativeGeoTargetType(GeoTargetTypeSettingNegativeGeoTargetType.DONT_CARE);
                                                                    } else if (geoTargetChildren.item(ch).getTextContent().equalsIgnoreCase("L")) {
                                                                        geoSetting.setNegativeGeoTargetType(GeoTargetTypeSettingNegativeGeoTargetType.LOCATION_OF_PRESENCE);
                                                                    }
                                                                }
                                                            }

                                                            settingsList.add(geoSetting);
                                                        }

                                                        if (settings.item(x).getNodeName().equalsIgnoreCase("RealTimeBidding")) {
                                                            RealTimeBiddingSetting realTimeSetting = new RealTimeBiddingSetting();
                                                            NodeList realTimeChildren = settings.item(x).getChildNodes();
                                                            for (int ch = 0; ch < realTimeChildren.getLength(); ch++) {
                                                                if (realTimeChildren.item(ch).getNodeName().equalsIgnoreCase("realtime")) {
                                                                    realTimeSetting.setOptIn(Boolean.parseBoolean(realTimeChildren.item(ch).getTextContent()));
                                                                }
                                                            }
                                                            settingsList.add(realTimeSetting);
                                                        }

                                                        if (settings.item(x).getNodeName().equalsIgnoreCase("Tracking")) {
                                                            TrackingSetting trackingSetting = new TrackingSetting();
                                                            NodeList trackingChildren = settings.item(x).getChildNodes();
                                                            for (int ch = 0; ch < trackingChildren.getLength(); ch++) {
                                                                if (trackingChildren.item(ch).getNodeName().equalsIgnoreCase("TrackingUrl")) {
                                                                    trackingSetting.setTrackingUrl(trackingChildren.item(ch).getTextContent());
                                                                }
                                                            }
                                                            settingsList.add(trackingSetting);
                                                        }

                                                        if (settings.item(x).getNodeName().equalsIgnoreCase("DynamicSearchAds")) {
                                                            DynamicSearchAdsSetting dynamicSearchAdsSetting = new DynamicSearchAdsSetting();
                                                            NodeList dynamicSearchAdsChildren = settings.item(x).getChildNodes();
                                                            for (int ch = 0; ch < dynamicSearchAdsChildren.getLength(); ch++) {
                                                                if (dynamicSearchAdsChildren.item(ch).getNodeName().equalsIgnoreCase("DomainName")) {
                                                                    dynamicSearchAdsSetting.setDomainName(dynamicSearchAdsChildren.item(ch).getTextContent());
                                                                }
                                                                if (dynamicSearchAdsChildren.item(ch).getNodeName().equalsIgnoreCase("LanguageCode")) {
                                                                    dynamicSearchAdsSetting.setLanguageCode(dynamicSearchAdsChildren.item(ch).getTextContent());
                                                                }
                                                            }
                                                            settingsList.add(dynamicSearchAdsSetting);
                                                        }
                                                    }
                                                    Setting[] settingsArray = new Setting[]{};
                                                    campaign.setSettings(settingsList.toArray(settingsArray));

                                                }

                                            }

                                            /** End Campaign Settings **/

                                            /** Start Campaign Network Settings **/

                                            if (nodeName.equalsIgnoreCase("NetworkSetting")) {

                                                NetworkSetting networkSetting = new NetworkSetting();

                                                NodeList networkChildren = node.getChildNodes();

                                                for (int x = 0; x < networkChildren.getLength(); x++) {

                                                    if (networkChildren.item(x).getNodeName().equalsIgnoreCase("NetworkGoogleSearch")) {
                                                        networkSetting.setTargetGoogleSearch(Boolean.parseBoolean(networkChildren.item(x).getTextContent()));
                                                    }

                                                    if (networkChildren.item(x).getNodeName().equalsIgnoreCase("NetworkSearchNetwork")) {
                                                        networkSetting.setTargetSearchNetwork(Boolean.parseBoolean(networkChildren.item(x).getTextContent()));
                                                    }

                                                    if (networkChildren.item(x).getNodeName().equalsIgnoreCase("NetworkContentNetwork")) {
                                                        networkSetting.setTargetContentNetwork(Boolean.parseBoolean(networkChildren.item(x).getTextContent()));
                                                    }

                                                    if (networkChildren.item(x).getNodeName().equalsIgnoreCase("NetworkPartnerSearchNetwork")) {
                                                        networkSetting.setTargetPartnerSearchNetwork(Boolean.parseBoolean(networkChildren.item(x).getTextContent()));
                                                    }
                                                }

                                                campaign.setNetworkSetting(networkSetting);

                                            }

                                            /** End Campaign Network Settings **/


                                        }

                                        gxIds.put(campaignName, gxId);
                                        campaigns.add(campaign);
                                    }
                                }
                            }
                        }

                        /** Start Create Budget **/

                        Budget budget = new Budget();
                        Long budgetGxId = 0L;

                        Long budgetId = 0L;

                        String budgetName = "";
                        for (int index = 0; index < children.getLength(); index++) {

                            Node budgetChildNode = children.item(index);

                            if (budgetChildNode.getNodeName().equalsIgnoreCase("Id")) {
                                budgetId = Long.parseLong(budgetChildNode.getTextContent());
                            }

                            if (budgetChildNode.getNodeName().equalsIgnoreCase("Name")) {
                                budget.setName(budgetChildNode.getTextContent());
                                budgetName = budgetChildNode.getTextContent();
                            }

                            if (budgetChildNode.getNodeName().equalsIgnoreCase("BudgetGxId")) {
                                budgetGxId = Long.parseLong(budgetChildNode.getTextContent());
                            }

                            if (budgetChildNode.getNodeName().equalsIgnoreCase("Period")) {
                                if (budgetChildNode.getTextContent().equalsIgnoreCase("D")) {
                                    budget.setPeriod(BudgetBudgetPeriod.DAILY);
                                }
                            }

                            if (budgetChildNode.getNodeName().equalsIgnoreCase("Shared")) {
                                budget.setIsExplicitlyShared(budgetChildNode.getTextContent().equalsIgnoreCase("true"));
                            }

                            if (budgetChildNode.getNodeName().equalsIgnoreCase("Amount")) {

                                Money budgetAmount = new Money();

                                Double amount = Double.parseDouble(budgetChildNode.getTextContent());

                                Long microAmount = (long) (amount * 10000000L / 10);

                                budgetAmount.setMicroAmount(microAmount);

                                budget.setAmount(budgetAmount);

                            }

                            if (budgetChildNode.getNodeName().equalsIgnoreCase("DeliveryMethod")) {
                                if (budgetChildNode.getTextContent().equalsIgnoreCase("A")) {
                                    budget.setDeliveryMethod(BudgetBudgetDeliveryMethod.ACCELERATED);
                                } else if (budgetChildNode.getTextContent().equalsIgnoreCase("S")) {
                                    budget.setDeliveryMethod(BudgetBudgetDeliveryMethod.STANDARD);
                                }
                            }

                            if (budgetChildNode.getNodeName().equalsIgnoreCase("Status")) {

                                if (budgetChildNode.getTextContent().equalsIgnoreCase("A")) {
                                    budget.setStatus(BudgetBudgetStatus.ENABLED);
                                }
                                if (budgetChildNode.getTextContent().equalsIgnoreCase("D")) {
                                    budget.setStatus(BudgetBudgetStatus.REMOVED);
                                }
                                if (budgetChildNode.getTextContent().equalsIgnoreCase("U")) {
                                    budget.setStatus(BudgetBudgetStatus.UNKNOWN);
                                }

                            }


                        }

                        budgetGxIds.put(budgetName, budgetGxId);

                        // Create the ADD operation to the budget
                        BudgetOperation operation = new BudgetOperation();
                        operation.setOperand(budget);
                        operation.setOperator(Operator.ADD);


                        /** End Create Budget **/

                        /** Set Budget to campaigns, and create Campaigns **/

                        int campaignsCreated = 0;
                        // Get budget service
                        BudgetServiceInterface budgetService = sf.GetBudgetService(this.GetClientId());
                        for (Campaign cmp : campaigns) {


                            GA_ResultItem createCampaign = new GA_ResultItem();
                            try {

                                if (budgetId == 0L) {
                                    budgetId = budgetService.mutate(new BudgetOperation[]{operation}).getValue(0).getBudgetId();
                                    Thread.sleep(1000);
                                    budget.setBudgetId(budgetId);

                                    budgetsCreated.put(budgetGxId, budget);
                                } else {
                                    budget.setBudgetId(budgetId);
                                }

                                createCampaign.SubCampName = cmp.getName();

                                cmp.setBudget(budget);
                                CampaignOperation campaignOperation = new CampaignOperation();
                                campaignOperation.setOperand(cmp);
                                campaignOperation.setOperator(Operator.ADD);

                                CampaignReturnValue returnValue = null;
                                // Get campaign service
                                CampaignServiceInterface campaignService = sf.GetCampaignService(this.GetClientId());

                                returnValue = campaignService.mutate(new CampaignOperation[]{campaignOperation});

                                Thread.sleep(1000);

                                createCampaign.CampaignId = returnValue.getValue(0).getId();

                                createCampaign.BudgetId = budgetId;
                                createCampaign.SubCampaignGxId = gxIds.get(cmp.getName());
                                createCampaign.BudgetGxId = budgetGxIds.get(budgetName);
                                createCampaign.HasError = false;

                                campaignsCreated++;

                            } catch (ApiException apiException) {


                                boolean retry = false;

                                ApiError[] apiErrors = apiException.getErrors();

                                for (ApiError error : apiErrors) {

                                    if (error.getErrorString().equalsIgnoreCase("RateExceededError.RATE_EXCEEDED")) {

                                        Thread.sleep(35000);

                                        if (budgetsCreated.get(budgetGxId) == null) {

                                            if (budgetId == 0L) {

                                                budgetId = budgetService.mutate(new BudgetOperation[]{operation}).getValue(0).getBudgetId();

                                                Thread.sleep(1000);
                                            }
                                            budget.setBudgetId(budgetId);

                                            budgetsCreated.put(budgetGxId, budget);


                                            createCampaign.SubCampName = cmp.getName();

                                            cmp.setBudget(budget);
                                            CampaignOperation campaignOperation = new CampaignOperation();
                                            campaignOperation.setOperand(cmp);
                                            campaignOperation.setOperator(Operator.ADD);
                                            createCampaign.BudgetId = budgetId;
                                            createCampaign.SubCampaignGxId = gxIds.get(cmp.getName());
                                            createCampaign.BudgetGxId = budgetGxIds.get(budgetName);

                                            CampaignReturnValue returnValue = null;
                                            // Get campaign service
                                            CampaignServiceInterface campaignService = sf.GetCampaignService(this.GetClientId());

                                            returnValue = campaignService.mutate(new CampaignOperation[]{campaignOperation});

                                            Thread.sleep(1000);

                                            createCampaign.CampaignId = returnValue.getValue(0).getId();


                                            createCampaign.HasError = false;

                                            campaignsCreated++;
                                            retry = true;

                                        }
                                        break;

                                    }

                                }
                                if (!retry) {
                                    createCampaign.CampaignId = 0L;
                                    createCampaign.BudgetId = 0L;
                                    createCampaign.SubCampaignGxId = gxIds.get(cmp.getName());
                                    createCampaign.BudgetGxId = budgetGxIds.get(budgetName);
                                    createCampaign.HasError = true;


                                    for (ApiError apiError : apiErrors) {
                                        ErrorsStruct errors = new ErrorsStruct();

                                        errors.Message = apiError.getErrorString();

                                        errors.Errors = new ArrayList<com.genexususa.eo.google.data.Error>();

                                        com.genexususa.eo.google.data.Error err = new com.genexususa.eo.google.data.Error();

                                        err.ErrorString = apiError.getErrorString();
                                        err.fieldPath = apiError.getFieldPath();
                                        err.Reason = apiException.getFaultReason();
                                        err.Trigger = apiError.getTrigger();
                                        err.Type = apiError.getApiErrorType();

                                        errors.Errors.add(err);

                                        createCampaign.Errors = errors;


                                    }
                                }
                            }

                            res.Items.add(createCampaign);
                        }

                        if (campaignsCreated == 0) {
                            BudgetOperation opAux = new BudgetOperation();
                            opAux.setOperand(budgetsCreated.get(budgetGxId));
                            opAux.setOperator(Operator.REMOVE);

                            try {
                                budgetService.mutate(new BudgetOperation[]{opAux});
                                Thread.sleep(1000);
                                toRemove = null;
                            } catch (ApiException apiExc) {

                            } catch (RemoteException rExc) {

                            }
                        }


                    }
                }

            } catch (Exception exc) {

                // Remove the created budget if corresponds

                if (toRemove != null) {
                    BudgetOperation operation = new BudgetOperation();
                    operation.setOperand(toRemove);
                    operation.setOperator(Operator.REMOVE);

                    //GA_ResultCreateCampaign createCampaign = new GA_ResultCreateCampaign();

                    GA_ResultItem createCampaign = new GA_ResultItem();
                    // Get budget service
                    BudgetServiceInterface budgetService = sf.GetBudgetService(this.GetClientId());
                    try {
                        budgetService.mutate(new BudgetOperation[]{operation});
                        Thread.sleep(1000);
                    } catch (ApiException apiException) {


                        ApiError[] apiErrors = apiException.getErrors();

                        createCampaign.CampaignId = 0L;
                        createCampaign.BudgetId = 0L;
                        createCampaign.SubCampaignGxId = gxIds.get(createCampaign.SubCampName);
                        createCampaign.BudgetGxId = budgetGxIds.get(toRemove.getName());
                        createCampaign.HasError = true;


                        for (ApiError apiError : apiErrors) {
                            ErrorsStruct errors = new ErrorsStruct();

                            errors.Message = apiError.getErrorString();

                            errors.Errors = new ArrayList<com.genexususa.eo.google.data.Error>();

                            com.genexususa.eo.google.data.Error err = new com.genexususa.eo.google.data.Error();

                            err.ErrorString = apiError.getErrorString();
                            err.fieldPath = apiError.getFieldPath();
                            err.Reason = apiException.getFaultReason();
                            err.Trigger = apiError.getTrigger();
                            err.Type = apiError.getApiErrorType();

                            errors.Errors.add(err);

                            createCampaign.Errors = errors;


                        }

                        res.Items.add(createCampaign);

                    }
                }

                try {

                    JAXBContext contextObj = JAXBContext.newInstance(GA_Result.class);

                    Marshaller marshallerObj = contextObj.createMarshaller();
                    marshallerObj.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);

                    StringWriter sw = new StringWriter();

                    //res.Items = created

                    marshallerObj.marshal(res, sw);
                    result = sw.getBuffer().toString();
                    System.out.println(result);
                    String s = "";
                    return result;

                } catch (Exception excAux) {

                }
                throw exc;

            }

            try {

                JAXBContext contextObj = JAXBContext.newInstance(GA_Result.class);

                Marshaller marshallerObj = contextObj.createMarshaller();
                marshallerObj.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);

                StringWriter sw = new StringWriter();

                marshallerObj.marshal(res, sw);
                result = sw.getBuffer().toString();
                System.out.println(result);
                String s = "";

            } catch (Exception exc) {

            }
            return result;


        } catch (Exception exc) {

            GA_Result res = new GA_Result();
            ArrayList<GA_ResultItem> items = new ArrayList<GA_ResultItem>();
            GA_ResultItem error = new GA_ResultItem();
            ErrorsStruct errors = new ErrorsStruct();
            errors.Message = exc.getMessage();
            errors.Errors = new ArrayList<com.genexususa.eo.google.data.Error>();
            com.genexususa.eo.google.data.Error err = new com.genexususa.eo.google.data.Error();
            StringWriter st = new StringWriter();
            exc.printStackTrace(new PrintWriter(st));
            err.UnknownError = st.toString();
            errors.Errors.add(err);
            error.Errors = errors;
            error.HasError = true;
            items.add(error);
            String result = "";
            try {

                JAXBContext contextObj = JAXBContext.newInstance(GA_Result.class);
                Marshaller marshallerObj = contextObj.createMarshaller();
                marshallerObj.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
                StringWriter sw = new StringWriter();
                res.Items = items;
                marshallerObj.marshal(res, sw);
                result = sw.getBuffer().toString();
                System.out.println(result);
                return result;

            } catch (Exception ex) {
                ex.printStackTrace();
                result = ex.getMessage();
                return result;
            }
        }
    }

    public String CreateBudget(String xml) {
        try {
            String result = "";
            GA_Result res = new GA_Result();
            // Get the instance of service's factory
            ServiceFactory sf = ServiceFactory.getInstance();

            // Get campaign service
            CampaignServiceInterface campaignService = sf.GetCampaignService(this.GetClientId());

            // Get budget service
            BudgetServiceInterface budgetService = sf.GetBudgetService(this.GetClientId());
            HashMap<String, Long> budgetGxIds = new HashMap<String, Long>();
            Document doc = loadXMLFromString(xml);
            XPathFactory factory = XPathFactory.newInstance();
            XPath xpath = factory.newXPath();
            XPathExpression expr
                    = xpath.compile("//Budget");
            Object budgetNodes = expr.evaluate(doc, XPathConstants.NODESET);
            NodeList budgets = (NodeList) budgetNodes;
            if (budgets.getLength() > 0) {
                ArrayList<Budget> budgetsArray = new ArrayList<Budget>();
                for (int i = 0; i < budgets.getLength(); i++) {
                    Node n = budgets.item(i);
                    NodeList children = n.getChildNodes(); // Children of budget node
                    Long budgetGxId = 0L;
                    String budgetName = "";
                    Budget budget = new Budget();
                    for (int index = 0; index < children.getLength(); index++) {
                        Node budgetChildNode = children.item(index);
                        if (budgetChildNode.getNodeName().equalsIgnoreCase("Name")) {
                            budget.setName(budgetChildNode.getTextContent());
                            budgetName = budgetChildNode.getTextContent();
                        }
                        if (budgetChildNode.getNodeName().equalsIgnoreCase("BudgetGxId")) {
                            budgetGxId = Long.parseLong(budgetChildNode.getTextContent());
                        }
                        if (budgetChildNode.getNodeName().equalsIgnoreCase("Period")) {
                            if (budgetChildNode.getTextContent().equalsIgnoreCase("D")) {
                                budget.setPeriod(BudgetBudgetPeriod.DAILY);
                            }
                        }
                        if (budgetChildNode.getNodeName().equalsIgnoreCase("Amount")) {
                            Money budgetAmount = new Money();
                            Double amount = Double.parseDouble(budgetChildNode.getTextContent());
                            Long microAmount = (long) (amount * 10000000L / 10);
                            budgetAmount.setMicroAmount(microAmount);
                            budget.setAmount(budgetAmount);
                        }

                        if (budgetChildNode.getNodeName().equalsIgnoreCase("DeliveryMethod")) {
                            if (budgetChildNode.getTextContent().equalsIgnoreCase("A")) {
                                budget.setDeliveryMethod(BudgetBudgetDeliveryMethod.ACCELERATED);
                            } else if (budgetChildNode.getTextContent().equalsIgnoreCase("S")) {
                                budget.setDeliveryMethod(BudgetBudgetDeliveryMethod.STANDARD);
                            }
                        }

                        if (budgetChildNode.getNodeName().equalsIgnoreCase("Status")) {
                            if (budgetChildNode.getTextContent().equalsIgnoreCase("A")) {
                                budget.setStatus(BudgetBudgetStatus.ENABLED);
                            }
                            if (budgetChildNode.getTextContent().equalsIgnoreCase("D")) {
                                budget.setStatus(BudgetBudgetStatus.REMOVED);
                            }
                            if (budgetChildNode.getTextContent().equalsIgnoreCase("U")) {
                                budget.setStatus(BudgetBudgetStatus.UNKNOWN);
                            }
                        }
                    }
                    budgetsArray.add(budget);
                    budgetGxIds.put(budgetName, budgetGxId);
                }
                for (Budget budget : budgetsArray) {
                    GA_ResultItem createBudget = new GA_ResultItem();
                    // Create the ADD operation to the budget
                    BudgetOperation operation = new BudgetOperation();
                    operation.setOperand(budget);
                    operation.setOperator(Operator.ADD);
                    createBudget.BudgetGxId = budgetGxIds.get(budget.getName());
                    try {
                        Long budgetId = budgetService.mutate(new BudgetOperation[]{operation}).getValue(0).getBudgetId();
                        Thread.sleep(1000);
                        createBudget.BudgetId = budgetId;
                    } catch (ApiException apiException) {
                        boolean retry = false;
                        ApiError[] apiErrors = apiException.getErrors();
                        for (ApiError error : apiErrors) {
                            if (error.getErrorString().equalsIgnoreCase("RateExceededError.RATE_EXCEEDED")) {
                                Thread.sleep(35000);
                                Long budgetId = budgetService.mutate(new BudgetOperation[]{operation}).getValue(0).getBudgetId();
                                Thread.sleep(1000);
                                createBudget.BudgetId = budgetId;
                                retry = true;
                            }
                        }
                        if (!retry) {
                            createBudget.CampaignId = 0L;
                            createBudget.BudgetId = 0L;
                            createBudget.BudgetGxId = budgetGxIds.get(budget.getName());
                            createBudget.HasError = true;
                            for (ApiError apiError : apiErrors) {
                                ErrorsStruct errors = new ErrorsStruct();
                                errors.Message = apiError.getErrorString();
                                errors.Errors = new ArrayList<com.genexususa.eo.google.data.Error>();
                                com.genexususa.eo.google.data.Error err = new com.genexususa.eo.google.data.Error();
                                err.ErrorString = apiError.getErrorString();
                                err.fieldPath = apiError.getFieldPath();
                                err.Reason = apiException.getFaultReason();
                                err.Trigger = apiError.getTrigger();
                                err.Type = apiError.getApiErrorType();
                                errors.Errors.add(err);
                                createBudget.Errors = errors;
                            }
                        }
                    }
                    res.Items.add(createBudget);
                }
            }

            try {
                JAXBContext contextObj = JAXBContext.newInstance(GA_Result.class);
                Marshaller marshallerObj = contextObj.createMarshaller();
                marshallerObj.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
                StringWriter sw = new StringWriter();
                marshallerObj.marshal(res, sw);
                result = sw.getBuffer().toString();
                System.out.println(result);
                String s = "";
                return result;

            } catch (Exception excAux) {

            }
            return result;

        } catch (Exception exc) {
            GA_Result res = new GA_Result();
            ArrayList<GA_ResultItem> items = new ArrayList<GA_ResultItem>();
            GA_ResultItem error = new GA_ResultItem();
            ErrorsStruct errors = new ErrorsStruct();
            errors.Message = exc.getMessage();
            errors.Errors = new ArrayList<com.genexususa.eo.google.data.Error>();
            com.genexususa.eo.google.data.Error err = new com.genexususa.eo.google.data.Error();
            StringWriter st = new StringWriter();
            exc.printStackTrace(new PrintWriter(st));
            err.UnknownError = st.toString();
            errors.Errors.add(err);
            error.Errors = errors;
            error.HasError = true;
            items.add(error);
            String result = "";
            try {

                JAXBContext contextObj = JAXBContext.newInstance(GA_Result.class);
                Marshaller marshallerObj = contextObj.createMarshaller();
                marshallerObj.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
                StringWriter sw = new StringWriter();
                res.Items = items;
                marshallerObj.marshal(res, sw);
                result = sw.getBuffer().toString();
                System.out.println(result);
                return result;

            } catch (Exception ex) {
                ex.printStackTrace();
                result = ex.getMessage();
                return result;
            }
        }
    }

    public String UpdateCampaign(String xml) {
        try {
            String result = "";
            GA_Result res = new GA_Result();
            // Get the instance of service's factory
            ServiceFactory sf = ServiceFactory.getInstance();
            HashMap<String, Long> gxIds = new HashMap<String, Long>();
            Document doc = loadXMLFromString(xml);
            XPathFactory factory = XPathFactory.newInstance();
            XPath xpath = factory.newXPath();
            XPathExpression expr
                    = xpath.compile("//Budget");
            Object budgetNodes = expr.evaluate(doc, XPathConstants.NODESET);
            NodeList budgets = (NodeList) budgetNodes;
            if (budgets.getLength() > 0) {
                for (int i = 0; i < budgets.getLength(); i++) {
                    Node n = budgets.item(i);
                    NodeList children = n.getChildNodes(); // Children of budget node
                    ArrayList<Campaign> campaigns = new ArrayList<Campaign>();
                    for (int j = 0; j < children.getLength(); j++) {
                        Node child = children.item(j);
                        NodeList budgetChildren = child.getChildNodes();
                        if (budgetChildren.getLength() > 0) {
                            for (int h = 0; h < budgetChildren.getLength(); h++) {
                                if (budgetChildren.item(h).getNodeName().equalsIgnoreCase("SubCampaign")) {
                                    NodeList campaignChildren = budgetChildren.item(h).getChildNodes();
                                    Campaign campaign = new Campaign();
                                    String campaignName = "";
                                    Long gxId = 0L;
                                    for (int z = 0; z < campaignChildren.getLength(); z++) {
                                        Node node = campaignChildren.item(z);
                                        String nodeName = node.getNodeName();
                                        /** Start Campaign ID **/
                                        if (nodeName.equalsIgnoreCase("Id")) {
                                            campaign.setId(Long.parseLong(campaignChildren.item(z).getTextContent()));
                                        }
                                        /** End Campaign ID **/

                                        /** Start Campaign Name **/
                                        if (nodeName.equalsIgnoreCase("Name")) {
                                            campaign.setName(campaignChildren.item(z).getTextContent());
                                            campaignName = campaignChildren.item(z).getTextContent();
                                        }
                                        /** End Campaign Name **/

                                        if (nodeName.equalsIgnoreCase("SubCampaignGXId")) {
                                            gxId = Long.parseLong(campaignChildren.item(z).getTextContent());
                                        }

                                        /** Start Campaign Status **/
                                        if (nodeName.equalsIgnoreCase("Status")) {
                                            if (node.getTextContent().equalsIgnoreCase("A")) {
                                                campaign.setStatus(CampaignStatus.ENABLED);
                                            } else if (node.getTextContent().equalsIgnoreCase("P")) {
                                                campaign.setStatus(CampaignStatus.PAUSED);
                                            } else if (node.getTextContent().equalsIgnoreCase("D")) {
                                                campaign.setStatus(CampaignStatus.REMOVED);
                                            }
                                        }

                                        /** End Campaign Status **/

                                        if (nodeName.equalsIgnoreCase("AdvertisingChannelType")) {
                                            if (campaignChildren.item(z).getTextContent() != ""){
                                                try{
                                                    campaign.setAdvertisingChannelType(AdvertisingChannelType.fromString(campaignChildren.item(z).getTextContent()));
                                                }catch (Exception e){
                                                    campaign.setAdvertisingChannelType(AdvertisingChannelType.SEARCH);
                                                }
                                            }else{
                                                campaign.setAdvertisingChannelType(AdvertisingChannelType.SEARCH);
                                            }
                                        }

                                        /** Start Campaign Serving Status **/

                                        if (nodeName.equalsIgnoreCase("ServingStatus")) {
                                            if (node.getTextContent().equalsIgnoreCase("S")) {
                                                campaign.setServingStatus(ServingStatus.SERVING);
                                            }
                                            if (node.getTextContent().equalsIgnoreCase("N")) {
                                                campaign.setServingStatus(ServingStatus.NONE);
                                            }
                                            if (node.getTextContent().equalsIgnoreCase("E")) {
                                                campaign.setServingStatus(ServingStatus.ENDED);
                                            }
                                            if (node.getTextContent().equalsIgnoreCase("P")) {
                                                campaign.setServingStatus(ServingStatus.PENDING);
                                            }
                                            if (node.getTextContent().equalsIgnoreCase("SU")) {
                                                campaign.setServingStatus(ServingStatus.SUSPENDED);
                                            }
                                        }

                                        /** End Campaign Serving Status **/

                                        /** Start Campaign Start Date **/

                                        if (nodeName.equalsIgnoreCase("StartDate")) {
                                            String sd = node.getTextContent();

                                            try {

                                                DateTimeFormatter df = DateTimeFormat.forPattern("yyyy-MM-dd");
                                                DateTime dateTime = df.parseDateTime(sd);

                                                campaign.setStartDate(dateTime.toString("yyyyMMdd"));
                                            } catch (IllegalArgumentException exc) {

                                            }
                                        }

                                        /** End Campaign Start Date **/

                                        /** Start Campaign End Date **/

                                        if (nodeName.equalsIgnoreCase("EndDate")) {
                                            String ed = node.getTextContent();

                                            try {

                                                DateTimeFormatter df = DateTimeFormat.forPattern("yyyy-MM-dd");
                                                DateTime dateTime = df.parseDateTime(ed);

                                                campaign.setEndDate(dateTime.toString("yyyyMMdd"));
                                            } catch (IllegalArgumentException exc) {

                                            }
                                        }

                                        /** End Campaign End Date **/

                                        //region Bidding Strategies
                                        /** Start Campaign Bidding Strategies **/

                                        if (nodeName.equalsIgnoreCase("BiddingStrategyConfiguration")) {

                                            NodeList biddingStrategyConfiguration = node.getChildNodes();

                                            if (biddingStrategyConfiguration.getLength() > 0) {
                                                for (int a=0; a<biddingStrategyConfiguration.getLength(); a++) {
                                                    BiddingStrategyConfiguration bsc = new BiddingStrategyConfiguration();
                                                    if (biddingStrategyConfiguration.item(a).getNodeName().equalsIgnoreCase("BiddingScheme")) {

                                                        NodeList strategies = biddingStrategyConfiguration.item(a).getChildNodes();

                                                        if (strategies.getLength() > 0) {

                                                            for (int y = 0; y < strategies.getLength(); y++) {

                                                                if (strategies.item(y).getNodeName().equalsIgnoreCase("BSConversionOptimizer")) {
                                                                    Node bsConversionOptimizer = strategies.item(y);

                                                                    NodeList bsConversionOptimizerChildren = bsConversionOptimizer.getChildNodes();

                                                                    if (bsConversionOptimizerChildren.getLength() > 0) {

                                                                        ConversionOptimizerBiddingScheme co = new ConversionOptimizerBiddingScheme();

                                                                        for (int index = 0; index < bsConversionOptimizerChildren.getLength(); index++) {

                                                                            if (bsConversionOptimizerChildren.item(index).getNodeName().equalsIgnoreCase("BSConvOptPricingModel")) {
                                                                                if (bsConversionOptimizerChildren.item(index).getTextContent().equalsIgnoreCase("C")) {
                                                                                    co.setPricingMode(ConversionOptimizerBiddingSchemePricingMode.CLICKS);
                                                                                } else if (bsConversionOptimizerChildren.item(index).getTextContent().equalsIgnoreCase("CN")) {
                                                                                    co.setPricingMode(ConversionOptimizerBiddingSchemePricingMode.CONVERSIONS);
                                                                                }
                                                                            }

                                                                            if (bsConversionOptimizerChildren.item(index).getNodeName().equalsIgnoreCase("BSConvOptBidType")) {
                                                                                if (bsConversionOptimizerChildren.item(index).getTextContent().equalsIgnoreCase("T")) {
                                                                                    co.setBidType(ConversionOptimizerBiddingSchemeBidType.TARGET_CPA);
                                                                                }/* else if (bsConversionOptimizerChildren.item(index).getTextContent().equalsIgnoreCase("M")) {
                                                                                    co.setBidType(ConversionOptimizerBiddingSchemeBidType.MAX_CPA);
                                                                                } */
                                                                            }
                                                                        }
                                                                        bsc.setBiddingScheme(co);
                                                                    }

                                                                }

                                                                if (strategies.item(y).getNodeName().equalsIgnoreCase("BSManualCPC")) {

                                                                    Node manualCPCNode = strategies.item(y);

                                                                    NodeList manualCPCChildren = manualCPCNode.getChildNodes();

                                                                    ManualCpcBiddingScheme manualCPC = new ManualCpcBiddingScheme();

                                                                    for (int index = 0; index < manualCPCChildren.getLength(); index++) {

                                                                        if (manualCPCChildren.item(index).getNodeName().equalsIgnoreCase("enhancedCpcEnabled")) {
                                                                            if (manualCPCChildren.item(index).getTextContent().equalsIgnoreCase("true")) {
                                                                                manualCPC.setEnhancedCpcEnabled(true);
                                                                            } else {
                                                                                manualCPC.setEnhancedCpcEnabled(false);
                                                                            }
                                                                        }
                                                                    }

                                                                    bsc.setBiddingScheme(manualCPC);
                                                                }

                                                                if (strategies.item(y).getNodeName().equalsIgnoreCase("BSManualCPM")) {
                                                                    Node manualCPMNode = strategies.item(y);

                                                                    NodeList manualCPMChildren = manualCPMNode.getChildNodes();

                                                                    for (int index = 0; index < manualCPMChildren.getLength(); index++) {

                                                                        if (manualCPMChildren.item(index).getNodeName().equalsIgnoreCase("enable")) {
                                                                            if (manualCPMChildren.item(index).getTextContent().equalsIgnoreCase("true")) {
                                                                                bsc.setBiddingScheme(new ManualCpmBiddingScheme());
                                                                            }
                                                                        }
                                                                    }
                                                                }

                                                                if (strategies.item(y).getNodeName().equalsIgnoreCase("BSEnhancedCPC")) {

                                                                    Node enhancedCPCNode = strategies.item(y);
                                                                    NodeList enhancedCPCChildren = enhancedCPCNode.getChildNodes();
                                                                    for (int index = 0; index < enhancedCPCChildren.getLength(); index++) {

                                                                        if (enhancedCPCChildren.item(index).getNodeName().equalsIgnoreCase("BiddingId")){
                                                                            bsc.setBiddingStrategyId(Long.parseLong(enhancedCPCChildren.item(index).getTextContent()));
                                                                        }

                                                                    }
                                                                }

                                                                if (strategies.item(y).getNodeName().equalsIgnoreCase("BSBudgetOptimizer")) {

                                                                    Node bsBudgetOptimizerNode = strategies.item(y);

                                                                    NodeList bsBudgetOptimizerNodeChildren = bsBudgetOptimizerNode.getChildNodes();

                                                                    BudgetOptimizerBiddingScheme bo = new BudgetOptimizerBiddingScheme();

                                                                    for (int index = 0; index < bsBudgetOptimizerNodeChildren.getLength(); index++) {

                                                                        if (bsBudgetOptimizerNodeChildren.item(index).getNodeName().equalsIgnoreCase("enhancedCpcEnabled")) {

                                                                            if (bsBudgetOptimizerNodeChildren.item(index).getTextContent().equalsIgnoreCase("true")) {
                                                                                bo.setEnhancedCpcEnabled(true);
                                                                            } else {
                                                                                bo.setEnhancedCpcEnabled(false);
                                                                            }
                                                                        }

                                                                        if (bsBudgetOptimizerNodeChildren.item(index).getNodeName().equalsIgnoreCase("bidCeiling")) {

                                                                            Money bidCeilingMoney = new Money();

                                                                            Double amount = Double.parseDouble(bsBudgetOptimizerNodeChildren.item(index).getTextContent());

                                                                            Long microAmount = (long) (amount * 10000000L / 10);
                                                                            bidCeilingMoney.setMicroAmount(microAmount);

                                                                            bo.setBidCeiling(bidCeilingMoney);
                                                                        }
                                                                    }

                                                                }
                                                            }
                                                            campaign.setBiddingStrategyConfiguration(bsc);
                                                        }
                                                    }
                                                }
                                            }
                                        }

                                        /** End Campaign Bidding Strategies **/
                                        //endregion

                                        /** Start Campaign Ad Serving Optimization Status **/

                                        if (nodeName.equalsIgnoreCase("AdServingOptimizationStatus")) {
                                            if (node.getTextContent().equalsIgnoreCase("O")) {
                                                campaign.setAdServingOptimizationStatus(AdServingOptimizationStatus.OPTIMIZE);
                                            } else if (node.getTextContent().equalsIgnoreCase("C")) {
                                                campaign.setAdServingOptimizationStatus(AdServingOptimizationStatus.CONVERSION_OPTIMIZE);
                                            } else if (node.getTextContent().equalsIgnoreCase("R")) {
                                                campaign.setAdServingOptimizationStatus(AdServingOptimizationStatus.ROTATE);
                                            } else if (node.getTextContent().equalsIgnoreCase("RI")) {
                                                campaign.setAdServingOptimizationStatus(AdServingOptimizationStatus.ROTATE_INDEFINITELY);
                                            } else if (node.getTextContent().equalsIgnoreCase("U")) {
                                                campaign.setAdServingOptimizationStatus(AdServingOptimizationStatus.UNAVAILABLE);
                                            }
                                        }

                                        /** End Campaign Ad Serving Optimization Status **/

                                        /** Start Campaign Frequency Cap **/

                                        if (nodeName.equalsIgnoreCase("FrequencyCap")) {

                                            NodeList frequencyCapNodeChildren = node.getChildNodes();

                                            if (frequencyCapNodeChildren.getLength() > 0) {

                                                FrequencyCap fc = new FrequencyCap();

                                                for (int index = 0; index < frequencyCapNodeChildren.getLength(); index++) {

                                                    if (frequencyCapNodeChildren.item(index).getNodeName().equalsIgnoreCase("FreqImpressions")) {
                                                        fc.setImpressions(Long.parseLong(frequencyCapNodeChildren.item(index).getTextContent()));
                                                    }

                                                    if (frequencyCapNodeChildren.item(index).getNodeName().equalsIgnoreCase("FreqLevel")) {

                                                        if (frequencyCapNodeChildren.item(index).getTextContent().equalsIgnoreCase("A")) {
                                                            fc.setLevel(Level.ADGROUP);
                                                        } else if (frequencyCapNodeChildren.item(index).getTextContent().equalsIgnoreCase("C")) {
                                                            fc.setLevel(Level.CREATIVE);
                                                        } else if (frequencyCapNodeChildren.item(index).getTextContent().equalsIgnoreCase("CM")) {
                                                            fc.setLevel(Level.CAMPAIGN);
                                                        } else if (frequencyCapNodeChildren.item(index).getTextContent().equalsIgnoreCase("U")) {
                                                            fc.setLevel(Level.UNKNOWN);
                                                        }

                                                    }

                                                    if (frequencyCapNodeChildren.item(index).getNodeName().equalsIgnoreCase("FreqTimeUnit")) {
                                                        if (frequencyCapNodeChildren.item(index).getTextContent().equalsIgnoreCase("M")) {
                                                            fc.setTimeUnit(TimeUnit.MINUTE);
                                                        } else if (frequencyCapNodeChildren.item(index).getTextContent().equalsIgnoreCase("H")) {
                                                            fc.setTimeUnit(TimeUnit.HOUR);
                                                        } else if (frequencyCapNodeChildren.item(index).getTextContent().equalsIgnoreCase("D")) {
                                                            fc.setTimeUnit(TimeUnit.DAY);
                                                        } else if (frequencyCapNodeChildren.item(index).getTextContent().equalsIgnoreCase("W")) {
                                                            fc.setTimeUnit(TimeUnit.WEEK);
                                                        } else if (frequencyCapNodeChildren.item(index).getTextContent().equalsIgnoreCase("MN")) {
                                                            fc.setTimeUnit(TimeUnit.MONTH);
                                                        } else if (frequencyCapNodeChildren.item(index).getTextContent().equalsIgnoreCase("L")) {
                                                            fc.setTimeUnit(TimeUnit.LIFETIME);
                                                        }
                                                    }

                                                }

                                                campaign.setFrequencyCap(fc);
                                            }
                                        }

                                        /** End Campaign Frequency Cap **/

                                        /** Start Campaign Settings **/

                                        if (nodeName.equalsIgnoreCase("Settings")) {

                                            NodeList settings = node.getChildNodes();

                                            ArrayList<Setting> settingsList = new ArrayList<Setting>();

                                            if (settings.getLength() > 0) {

                                                for (int x = 0; x < settings.getLength(); x++) {

                                                    if (settings.item(x).getNodeName().equalsIgnoreCase("GeoTargetTypeSetting")) {

                                                        GeoTargetTypeSetting geoSetting = new GeoTargetTypeSetting();

                                                        NodeList geoTargetChildren = settings.item(x).getChildNodes();

                                                        for (int ch = 0; ch < geoTargetChildren.getLength(); ch++) {

                                                            if (geoTargetChildren.item(ch).getNodeName().equalsIgnoreCase("GeoTargetPositiveType")) {
                                                                if (geoTargetChildren.item(ch).getTextContent().equalsIgnoreCase("D")) {
                                                                    geoSetting.setPositiveGeoTargetType(GeoTargetTypeSettingPositiveGeoTargetType.DONT_CARE);
                                                                } else if (geoTargetChildren.item(ch).getTextContent().equalsIgnoreCase("A")) {
                                                                    geoSetting.setPositiveGeoTargetType(GeoTargetTypeSettingPositiveGeoTargetType.AREA_OF_INTEREST);
                                                                } else if (geoTargetChildren.item(ch).getTextContent().equalsIgnoreCase("l")) {
                                                                    geoSetting.setPositiveGeoTargetType(GeoTargetTypeSettingPositiveGeoTargetType.LOCATION_OF_PRESENCE);
                                                                }
                                                            }

                                                            if (geoTargetChildren.item(ch).getNodeName().equalsIgnoreCase("GeoTargetNegativeType")) {
                                                                if (geoTargetChildren.item(ch).getTextContent().equalsIgnoreCase("D")) {
                                                                    geoSetting.setNegativeGeoTargetType(GeoTargetTypeSettingNegativeGeoTargetType.DONT_CARE);
                                                                } else if (geoTargetChildren.item(ch).getTextContent().equalsIgnoreCase("L")) {
                                                                    geoSetting.setNegativeGeoTargetType(GeoTargetTypeSettingNegativeGeoTargetType.LOCATION_OF_PRESENCE);
                                                                }
                                                            }
                                                        }

                                                        settingsList.add(geoSetting);
                                                    }

                                                    if (settings.item(x).getNodeName().equalsIgnoreCase("RealTimeBidding")) {

                                                        RealTimeBiddingSetting realTimeSetting = new RealTimeBiddingSetting();

                                                        NodeList realTimeChildren = settings.item(x).getChildNodes();

                                                        for (int ch = 0; ch < realTimeChildren.getLength(); ch++) {
                                                            if (realTimeChildren.item(ch).getNodeName().equalsIgnoreCase("realtime")) {
                                                                realTimeSetting.setOptIn(Boolean.parseBoolean(realTimeChildren.item(ch).getTextContent()));
                                                            }
                                                        }

                                                        settingsList.add(realTimeSetting);
                                                    }

                                                    if (settings.item(x).getNodeName().equalsIgnoreCase("Tracking")) {

                                                        TrackingSetting trackingSetting = new TrackingSetting();

                                                        NodeList trackingChildren = settings.item(x).getChildNodes();

                                                        for (int ch = 0; ch < trackingChildren.getLength(); ch++) {
                                                            if (trackingChildren.item(ch).getNodeName().equalsIgnoreCase("TrackingUrl")) {
                                                                trackingSetting.setTrackingUrl(trackingChildren.item(ch).getTextContent());
                                                            }
                                                        }

                                                        settingsList.add(trackingSetting);
                                                    }
                                                }

                                                Setting[] settingsArray = new Setting[]{};
                                                campaign.setSettings(settingsList.toArray(settingsArray));

                                            }

                                        }

                                        /** End Campaign Settings **/

                                        /** Start Campaign Network Settings **/

                                        if (nodeName.equalsIgnoreCase("NetworkSetting")) {

                                            NetworkSetting networkSetting = new NetworkSetting();

                                            NodeList networkChildren = node.getChildNodes();

                                            for (int x = 0; x < networkChildren.getLength(); x++) {

                                                if (networkChildren.item(x).getNodeName().equalsIgnoreCase("NetworkGoogleSearch")) {
                                                    networkSetting.setTargetGoogleSearch(Boolean.parseBoolean(networkChildren.item(x).getTextContent()));
                                                }

                                                if (networkChildren.item(x).getNodeName().equalsIgnoreCase("NetworkSearchNetwork")) {
                                                    networkSetting.setTargetSearchNetwork(Boolean.parseBoolean(networkChildren.item(x).getTextContent()));
                                                }

                                                if (networkChildren.item(x).getNodeName().equalsIgnoreCase("NetworkContentNetwork")) {
                                                    networkSetting.setTargetContentNetwork(Boolean.parseBoolean(networkChildren.item(x).getTextContent()));
                                                }

                                                if (networkChildren.item(x).getNodeName().equalsIgnoreCase("NetworkPartnerSearchNetwork")) {
                                                    networkSetting.setTargetPartnerSearchNetwork(Boolean.parseBoolean(networkChildren.item(x).getTextContent()));
                                                }
                                            }

                                            campaign.setNetworkSetting(networkSetting);

                                        }

                                        /** End Campaign Network Settings **/


                                    }

                                    gxIds.put(campaignName, gxId);

                                    campaigns.add(campaign);
                                }
                            }
                        }
                    }

                    /** Set Budget to campaigns, and create Campaigns **/

                    // Get campaign service
                    CampaignServiceInterface campaignService = sf.GetCampaignService(this.GetClientId());

                    for (Campaign cmp : campaigns) {


                        //GA_ResultCreateCampaign createCampaign = new GA_ResultCreateCampaign();
                        GA_ResultItem createCampaign = new GA_ResultItem();
                        try {

                            createCampaign.SubCampName = cmp.getName();

                            CampaignOperation campaignOperation = new CampaignOperation();
                            campaignOperation.setOperand(cmp);
                            campaignOperation.setOperator(Operator.SET);

                            CampaignReturnValue returnValue = null;

                            returnValue = campaignService.mutate(new CampaignOperation[]{campaignOperation});

                            Thread.sleep(1000);

                            createCampaign.CampaignId = returnValue.getValue(0).getId();

                            createCampaign.SubCampaignGxId = gxIds.get(createCampaign.SubCampName);
                            createCampaign.HasError = false;


                        } catch (ApiException apiException) {


                            ApiError[] apiErrors = apiException.getErrors();

                            createCampaign.CampaignId = 0L;
                            createCampaign.SubCampaignGxId = gxIds.get(createCampaign.SubCampName);
                            createCampaign.BudgetId = 0L;
                            createCampaign.HasError = true;


                            for (ApiError apiError : apiErrors) {
                                ErrorsStruct errors = new ErrorsStruct();

                                errors.Message = apiError.getErrorString();

                                errors.Errors = new ArrayList<com.genexususa.eo.google.data.Error>();

                                com.genexususa.eo.google.data.Error err = new com.genexususa.eo.google.data.Error();

                                err.ErrorString = apiError.getErrorString();
                                err.fieldPath = apiError.getFieldPath();
                                err.Reason = apiException.getFaultReason();
                                err.Trigger = apiError.getTrigger();
                                err.Type = apiError.getApiErrorType();

                                errors.Errors.add(err);

                                createCampaign.Errors = errors;


                            }
                        }

                        res.Items.add(createCampaign);
                    }


                }
            }


            try {

                JAXBContext contextObj = JAXBContext.newInstance(GA_Result.class);

                Marshaller marshallerObj = contextObj.createMarshaller();
                marshallerObj.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);

                StringWriter sw = new StringWriter();

                marshallerObj.marshal(res, sw);
                result = sw.getBuffer().toString();
                System.out.println(result);
                String s = "";

            } catch (Exception exc) {
                System.out.println(exc.getMessage());
                exc.printStackTrace();

            }
            return result;

        } catch (Exception exc) {
            GA_Result res = new GA_Result();
            ArrayList<GA_ResultItem> items = new ArrayList<GA_ResultItem>();
            GA_ResultItem error = new GA_ResultItem();
            ErrorsStruct errors = new ErrorsStruct();
            errors.Message = exc.getMessage();
            errors.Errors = new ArrayList<com.genexususa.eo.google.data.Error>();
            com.genexususa.eo.google.data.Error err = new com.genexususa.eo.google.data.Error();
            StringWriter st = new StringWriter();
            exc.printStackTrace(new PrintWriter(st));
            err.UnknownError = st.toString();
            errors.Errors.add(err);
            error.Errors = errors;
            error.HasError = true;
            items.add(error);
            String result = "";

            try {

                JAXBContext contextObj = JAXBContext.newInstance(GA_Result.class);

                Marshaller marshallerObj = contextObj.createMarshaller();
                marshallerObj.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);

                StringWriter sw = new StringWriter();

                res.Items = items;

                marshallerObj.marshal(res, sw);
                result = sw.getBuffer().toString();
                System.out.println(result);
                return result;

            } catch (Exception ex) {
                ex.printStackTrace();
                result = ex.getMessage();
                return result;
            }
        }


    }

    public String UpdateBudget(String xml) {
        try {

            String result = "";

            //GA_ResultCreateCampaigns res = new GA_ResultCreateCampaigns();

            GA_Result res = new GA_Result();

            // Get the instance of service's factory
            ServiceFactory sf = ServiceFactory.getInstance();

            // Get budget service
            BudgetServiceInterface budgetService = sf.GetBudgetService(this.GetClientId());

            ArrayList<Budget> budgetObjects = new ArrayList<Budget>();

            HashMap<String, Long> budgetGxIds = new HashMap<String, Long>();


            Document doc = loadXMLFromString(xml);

            XPathFactory factory = XPathFactory.newInstance();
            XPath xpath = factory.newXPath();

            XPathExpression expr
                    = xpath.compile("//Budget");

            Object budgetNodes = expr.evaluate(doc, XPathConstants.NODESET);

            NodeList budgets = (NodeList) budgetNodes;

            if (budgets.getLength() > 0) {


                ArrayList<Budget> modifiedBudgets = new ArrayList<Budget>();

                for (int i = 0; i < budgets.getLength(); i++) {

                    Node n = budgets.item(i);

                    NodeList children = n.getChildNodes(); // Children of budget node

                    Long budgetId = 0L;

                    for (int j = 0; j < children.getLength(); j++) {

                        if (children.item(j).getNodeName().equalsIgnoreCase("Id")) {
                            budgetId = Long.parseLong(children.item(j).getTextContent());
                            break;
                        }
                    }

                    Budget budget = new Budget();

                    int offset = 0;

                    if (!budgetId.equals(0L)) {

                        Selector selector = new Selector();

                        selector.setFields(new String[]{"BudgetId", "DeliveryMethod", "BudgetName", "Period", "Amount", "BudgetStatus"});
                        selector.setPaging(new Paging(0, PAGE_SIZE));

                        BudgetPage budgetPage = null;


                        if (budgetObjects.size() == 0) {


                            do {

                                budgetPage = budgetService.get(selector);

                                if (budgetPage.getEntries() != null) {

                                    for (Budget b : budgetPage.getEntries()) {
                                        budgetObjects.add(b);
                                    }
                                }

                                offset += PAGE_SIZE;
                                selector.getPaging().setStartIndex(offset);
                            } while (offset < budgetPage.getTotalNumEntries());


                        }
                        for (Budget b : budgetObjects) {
                            if (b.getBudgetId().equals(budgetId)) {
                                budget = b;
                                break;
                            }
                        }


                        if (budget != null) {

                            //budget = budgetPage.getEntries(0);

                            Long budgetGxId = 0L;

                            String budgetName = "";

                            for (int j = 0; j < children.getLength(); j++) {

                                Node budgetChildNode = children.item(j);

                                if (budgetChildNode.getNodeName().equalsIgnoreCase("Name")) {
                                    budget.setName(budgetChildNode.getTextContent());
                                    budgetName = budgetChildNode.getTextContent();
                                }

                                if (budgetChildNode.getNodeName().equalsIgnoreCase("Period")) {
                                    if (budgetChildNode.getTextContent().equalsIgnoreCase("D")) {
                                        budget.setPeriod(BudgetBudgetPeriod.DAILY);
                                    }
                                }

                                if (budgetChildNode.getNodeName().equalsIgnoreCase("BudgetGxId")) {
                                    budgetGxId = Long.parseLong(budgetChildNode.getTextContent());
                                }

                                if (budgetChildNode.getNodeName().equalsIgnoreCase("Amount")) {

                                    Money budgetAmount = new Money();

                                    Double amount = Double.parseDouble(budgetChildNode.getTextContent());

                                    Long microAmount = (long) (amount * 10000000L / 10);

                                    budgetAmount.setMicroAmount(microAmount);

                                    budget.setAmount(budgetAmount);

                                }

                                if (budgetChildNode.getNodeName().equalsIgnoreCase("DeliveryMethod")) {
                                    if (budgetChildNode.getTextContent().equalsIgnoreCase("A")) {
                                        budget.setDeliveryMethod(BudgetBudgetDeliveryMethod.ACCELERATED);
                                    } else if (budgetChildNode.getTextContent().equalsIgnoreCase("S")) {
                                        budget.setDeliveryMethod(BudgetBudgetDeliveryMethod.STANDARD);
                                    }
                                }

                                if (budgetChildNode.getNodeName().equalsIgnoreCase("Status")) {

                                    if (budgetChildNode.getTextContent().equalsIgnoreCase("A")) {
                                        budget.setStatus(BudgetBudgetStatus.ENABLED);
                                    }
                                    if (budgetChildNode.getTextContent().equalsIgnoreCase("D")) {
                                        budget.setStatus(BudgetBudgetStatus.REMOVED);
                                    }
                                    if (budgetChildNode.getTextContent().equalsIgnoreCase("U")) {
                                        budget.setStatus(BudgetBudgetStatus.UNKNOWN);
                                    }

                                }

                            }

                            budgetGxIds.put(budgetName, budgetGxId);
                            modifiedBudgets.add(budget);
                        }
                    }
                }

                for (Budget b : modifiedBudgets) {

                    //GA_ResultCreateCampaign mb = new GA_ResultCreateCampaign();

                    GA_ResultItem mb = new GA_ResultItem();

                    mb.BudgetId = b.getBudgetId();
                    mb.CampaignId = 0L;
                    mb.HasError = false;
                    mb.SubCampaignGxId = 0L;
                    mb.SubCampName = "";
                    mb.BudgetGxId = budgetGxIds.get(b.getName());

                    try {

                        BudgetOperation operation = new BudgetOperation();

                        operation.setOperand(b);
                        operation.setOperator(Operator.SET);

                        BudgetOperation[] operations = new BudgetOperation[]{operation};

                        BudgetReturnValue returnValue = budgetService.mutate(operations);

                        Thread.sleep(1000);
                    } catch (ApiException apiException) {
                        ApiError[] apiErrors = apiException.getErrors();

                        mb.HasError = true;

                        for (ApiError apiError : apiErrors) {
                            ErrorsStruct errors = new ErrorsStruct();

                            errors.Message = apiError.getErrorString();

                            errors.Errors = new ArrayList<com.genexususa.eo.google.data.Error>();

                            com.genexususa.eo.google.data.Error err = new com.genexususa.eo.google.data.Error();

                            err.ErrorString = apiError.getErrorString();
                            err.fieldPath = apiError.getFieldPath();
                            err.Reason = apiException.getFaultReason();
                            err.Trigger = apiError.getTrigger();
                            err.Type = apiError.getApiErrorType();

                            errors.Errors.add(err);

                            mb.Errors = errors;


                        }


                    }
                    res.Items.add(mb);
                }

                try {

                    JAXBContext contextObj = JAXBContext.newInstance(GA_Result.class);

                    Marshaller marshallerObj = contextObj.createMarshaller();
                    marshallerObj.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);

                    StringWriter sw = new StringWriter();

                    marshallerObj.marshal(res, sw);
                    result = sw.getBuffer().toString();
                    System.out.println(result);
                    String s = "";
                    return result;

                } catch (Exception excAux) {

                }


            }


            return result;

        } catch (Exception exc) {

            GA_Result res = new GA_Result();

            ArrayList<GA_ResultItem> items = new ArrayList<GA_ResultItem>();

            GA_ResultItem error = new GA_ResultItem();

            ErrorsStruct errors = new ErrorsStruct();

            errors.Message = exc.getMessage();

            errors.Errors = new ArrayList<com.genexususa.eo.google.data.Error>();

            com.genexususa.eo.google.data.Error err = new com.genexususa.eo.google.data.Error();

            StringWriter st = new StringWriter();
            exc.printStackTrace(new PrintWriter(st));

            err.UnknownError = st.toString();

            errors.Errors.add(err);

            error.Errors = errors;

            error.HasError = true;

            items.add(error);

            String result = "";

            try {

                JAXBContext contextObj = JAXBContext.newInstance(GA_Result.class);

                Marshaller marshallerObj = contextObj.createMarshaller();
                marshallerObj.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);

                StringWriter sw = new StringWriter();

                res.Items = items;

                marshallerObj.marshal(res, sw);
                result = sw.getBuffer().toString();
                System.out.println(result);
                return result;

            } catch (Exception ex) {
                ex.printStackTrace();
                result = ex.getMessage();
                return result;
            }
        }
    }


    public String SetBudget(Long campaignId, Long budgetId) {

        try {

            String result = "";


            GA_Result res = new GA_Result();

            // Get the instance of service's factory
            ServiceFactory sf = ServiceFactory.getInstance();

            // Get campaign service
            CampaignServiceInterface campaignService = sf.GetCampaignService(this.GetClientId());

            // Get budget service
            BudgetServiceInterface budgetService = sf.GetBudgetService(this.GetClientId());


            int offset = 0;
            Selector selector = new Selector();

            selector.setPaging(new Paging(offset, PAGE_SIZE));

            selector.setFields(new String[]
                    {
                            "BudgetId", "BudgetName", "Period", "Amount", "DeliveryMethod", "BudgetReferenceCount", "BudgetStatus"
                    });

            // Create predicates.
            Predicate budgetIdPredicate =
                    new Predicate("BudgetId", PredicateOperator.IN, new String[]{budgetId.toString()});

            selector.setPredicates(new Predicate[]{budgetIdPredicate});

            BudgetPage page = null;

            Budget budget = null;


            do {

                page = budgetService.get(selector);

                if (page.getEntries() != null) {

                    // Get the first one only (should be one)

                    budget = page.getEntries(0);

                    break;

                }


                offset += PAGE_SIZE;
                selector.getPaging().setStartIndex(offset);
            } while (offset < page.getTotalNumEntries());


            if (budget != null) {

                GA_ResultItem mc = new GA_ResultItem();

                offset = 0;
                selector = new Selector();

                selector.setPaging(new Paging(offset, PAGE_SIZE));

                selector.setFields(new String[]
                        {
                                "Id"
                        });

                // Create predicates.
                Predicate campaignIdPredicate =
                        new Predicate("Id", PredicateOperator.IN, new String[]{campaignId.toString()});

                selector.setPredicates(new Predicate[]{campaignIdPredicate});

                CampaignPage pageCampaign = null;

                Campaign campaign = null;

                pageCampaign = campaignService.get(selector);

                if (pageCampaign.getEntries() != null) {

                    // Get the first one only (should be one)

                    campaign = pageCampaign.getEntries(0);

                    if (campaign != null) {

                        campaign.setBudget(budget);

                        CampaignOperation campaignOperation = new CampaignOperation();
                        campaignOperation.setOperand(campaign);
                        campaignOperation.setOperator(Operator.SET);

                        CampaignReturnValue returnValue = null;

                        try {

                            returnValue = campaignService.mutate(new CampaignOperation[]{campaignOperation});

                            Thread.sleep(1000);

                            mc.CampaignId = returnValue.getValue(0).getId();
                            mc.BudgetId = budget.getBudgetId();
                        } catch (ApiException apiException) {

                            ApiError[] apiErrors = apiException.getErrors();

                            mc.HasError = true;

                            for (ApiError apiError : apiErrors) {
                                ErrorsStruct errors = new ErrorsStruct();
                                errors.Message = apiError.getErrorString();
                                errors.Errors = new ArrayList<com.genexususa.eo.google.data.Error>();
                                com.genexususa.eo.google.data.Error err = new com.genexususa.eo.google.data.Error();
                                err.ErrorString = apiError.getErrorString();
                                err.fieldPath = apiError.getFieldPath();
                                err.Reason = apiException.getFaultReason();
                                err.Trigger = apiError.getTrigger();
                                err.Type = apiError.getApiErrorType();
                                errors.Errors.add(err);
                                mc.Errors = errors;
                            }
                        }
                        res.Items.add(mc);
                    }
                }
            }

            try {

                JAXBContext contextObj = JAXBContext.newInstance(GA_Result.class);

                Marshaller marshallerObj = contextObj.createMarshaller();
                marshallerObj.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);

                StringWriter sw = new StringWriter();

                marshallerObj.marshal(res, sw);
                result = sw.getBuffer().toString();
                System.out.println(result);
                String s = "";
                return result;

            } catch (Exception excAux) {

            }


            return result;

        } catch (Exception exc) {

            GA_Result res = new GA_Result();
            ArrayList<GA_ResultItem> items = new ArrayList<GA_ResultItem>();
            GA_ResultItem error = new GA_ResultItem();
            ErrorsStruct errors = new ErrorsStruct();
            errors.Message = exc.getMessage();
            errors.Errors = new ArrayList<com.genexususa.eo.google.data.Error>();
            com.genexususa.eo.google.data.Error err = new com.genexususa.eo.google.data.Error();
            StringWriter st = new StringWriter();
            exc.printStackTrace(new PrintWriter(st));
            err.UnknownError = st.toString();
            errors.Errors.add(err);
            error.Errors = errors;
            error.HasError = true;
            items.add(error);
            String result = "";

            try {

                JAXBContext contextObj = JAXBContext.newInstance(GA_Result.class);
                Marshaller marshallerObj = contextObj.createMarshaller();
                marshallerObj.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
                StringWriter sw = new StringWriter();
                res.Items = items;
                marshallerObj.marshal(res, sw);
                result = sw.getBuffer().toString();
                System.out.println(result);
                return result;
            } catch (Exception ex) {
                ex.printStackTrace();
                result = ex.getMessage();
                return result;
            }
        }

    }


    protected ArrayList<GA_CampaignStats> GetCampaignStats() {

        ArrayList<GA_CampaignStats> result = new ArrayList<GA_CampaignStats>();

        // Get the instance of service's factory
        ServiceFactory sf = ServiceFactory.getInstance();

        try {
            // Get campaign service
            CampaignServiceInterface campaignService = sf.GetCampaignService(this.GetClientId());

            int offset = 0;
            Selector selector = new Selector();

            selector.setPaging(new Paging(offset, PAGE_SIZE));

            selector.setFields(new String[]
                    {
                            "AdServingOptimizationStatus",
                            "BidCeiling",
                            "BiddingStrategyType",
                            "BidType",
                            "BudgetId",
                            "EndDate",
                            "EnhancedCpcEnabled",
                            "FrequencyCapMaxImpressions",
                            "Id",
                            "Level",
                            "Name",
                            "PricingMode",
                            "StartDate",
                            "Status",
                            "Settings",
                            "TargetContentNetwork",
                            "TargetGoogleSearch",
                            "TargetPartnerSearchNetwork",
                            "TargetSearchNetwork",
                            "TimeUnit",
                    });

            Predicate predicate = new Predicate("Status", PredicateOperator.NOT_EQUALS, new String[]{"REMOVED"});
            Predicate[] predicates = new Predicate[]{predicate};
            selector.setPredicates(predicates);


            CampaignPage page = null;

            try {

                do {

                    page = campaignService.get(selector);

                    if (page.getEntries() != null) {

                        for (Campaign campaign : page.getEntries()) {

                            GA_CampaignStats stat = new GA_CampaignStats();

                            if (campaign.getAdServingOptimizationStatus() == AdServingOptimizationStatus.OPTIMIZE) {
                                stat.AdServingOptimizationStatus = "O";
                            } else if (campaign.getAdServingOptimizationStatus() == AdServingOptimizationStatus.CONVERSION_OPTIMIZE) {
                                stat.AdServingOptimizationStatus = "C";
                            } else if (campaign.getAdServingOptimizationStatus() == AdServingOptimizationStatus.ROTATE) {
                                stat.AdServingOptimizationStatus = "R";
                            } else if (campaign.getAdServingOptimizationStatus() == AdServingOptimizationStatus.ROTATE_INDEFINITELY) {
                                stat.AdServingOptimizationStatus = "RI";
                            } else if (campaign.getAdServingOptimizationStatus() == AdServingOptimizationStatus.UNAVAILABLE) {
                                stat.AdServingOptimizationStatus = "U";
                            }

                            if (campaign.getBiddingStrategyConfiguration().getBiddingStrategyType() == BiddingStrategyType.BUDGET_OPTIMIZER) {
                                stat.BiddingStrategyType = "BO";
                            } else if (campaign.getBiddingStrategyConfiguration().getBiddingStrategyType() == BiddingStrategyType.CONVERSION_OPTIMIZER) {
                                stat.BiddingStrategyType = "CO";
                            } else if (campaign.getBiddingStrategyConfiguration().getBiddingStrategyType() == BiddingStrategyType.MANUAL_CPC) {
                                stat.BiddingStrategyType = "MCPC";
                            } else if (campaign.getBiddingStrategyConfiguration().getBiddingStrategyType() == BiddingStrategyType.MANUAL_CPM) {
                                stat.BiddingStrategyType = "MCPM";
                            }

                            stat.BudgetId = campaign.getBudget().getBudgetId();
                            stat.EndDate = campaign.getEndDate();
                            stat.Id = campaign.getId();
                            stat.Name = campaign.getName();
                            stat.StartDate = campaign.getStartDate();

                            if (campaign.getStatus() == CampaignStatus.ENABLED) {
                                stat.Status = "A";
                            } else if (campaign.getStatus() == CampaignStatus.REMOVED) {
                                stat.Status = "D";
                            } else if (campaign.getStatus() == CampaignStatus.PAUSED) {
                                stat.Status = "P";
                            }

                            stat.TargetContentNetwork = campaign.getNetworkSetting().getTargetContentNetwork();
                            stat.TargetGoogleSearch = campaign.getNetworkSetting().getTargetGoogleSearch();
                            stat.TargetPartnerSearchNetwork = campaign.getNetworkSetting().getTargetPartnerSearchNetwork();
                            stat.TargetSearchNetwork = campaign.getNetworkSetting().getTargetSearchNetwork();

                            if (campaign.getFrequencyCap() != null) {
                                stat.FrequencyCapMaxImpressions = campaign.getFrequencyCap().getImpressions();
                                if (campaign.getFrequencyCap().getLevel() == Level.CREATIVE) {
                                    stat.Level = "C";
                                } else if (campaign.getFrequencyCap().getLevel() == Level.ADGROUP) {
                                    stat.Level = "A";
                                } else if (campaign.getFrequencyCap().getLevel() == Level.CAMPAIGN) {
                                    stat.Level = "CM";
                                } else if (campaign.getFrequencyCap().getLevel() == Level.UNKNOWN) {
                                    stat.Level = "U";
                                }

                                if (campaign.getFrequencyCap().getTimeUnit() == TimeUnit.MINUTE) {
                                    stat.TimeUnit = "M";
                                } else if (campaign.getFrequencyCap().getTimeUnit() == TimeUnit.HOUR) {
                                    stat.TimeUnit = "H";
                                } else if (campaign.getFrequencyCap().getTimeUnit() == TimeUnit.DAY) {
                                    stat.TimeUnit = "D";
                                } else if (campaign.getFrequencyCap().getTimeUnit() == TimeUnit.WEEK) {
                                    stat.TimeUnit = "W";
                                } else if (campaign.getFrequencyCap().getTimeUnit() == TimeUnit.MONTH) {
                                    stat.TimeUnit = "MN";
                                } else if (campaign.getFrequencyCap().getTimeUnit() == TimeUnit.LIFETIME) {
                                    stat.TimeUnit = "L";
                                }
                            }

                            BiddingScheme bs = campaign.getBiddingStrategyConfiguration().getBiddingScheme();
                            if (bs instanceof BudgetOptimizerBiddingScheme) {
                                if (((BudgetOptimizerBiddingScheme) campaign.getBiddingStrategyConfiguration().getBiddingScheme()).getBidCeiling() != null) {
                                    stat.BidCeiling = (double) ((BudgetOptimizerBiddingScheme) campaign.getBiddingStrategyConfiguration().getBiddingScheme()).getBidCeiling().getMicroAmount() / (double) 1000000;
                                }
                                stat.EnhancedCpcEnabled = ((BudgetOptimizerBiddingScheme) campaign.getBiddingStrategyConfiguration().getBiddingScheme()).getEnhancedCpcEnabled();
                            } else if (bs instanceof ConversionOptimizerBiddingScheme) {
                                if (((ConversionOptimizerBiddingScheme) campaign.getBiddingStrategyConfiguration().getBiddingScheme()).getBidType() == ConversionOptimizerBiddingSchemeBidType.TARGET_CPA) {
                                    stat.BidType = "T";
                                }

                                if (((ConversionOptimizerBiddingScheme) campaign.getBiddingStrategyConfiguration().getBiddingScheme()).getPricingMode() == ConversionOptimizerBiddingSchemePricingMode.CLICKS) {
                                    stat.PricingMode = "C";
                                } else if (((ConversionOptimizerBiddingScheme) campaign.getBiddingStrategyConfiguration().getBiddingScheme()).getPricingMode() == ConversionOptimizerBiddingSchemePricingMode.CONVERSIONS) {
                                    stat.PricingMode = "CN";
                                }
                            } else if (bs instanceof ManualCpcBiddingScheme) {
                                stat.EnhancedCpcEnabled = ((ManualCpcBiddingScheme) campaign.getBiddingStrategyConfiguration().getBiddingScheme()).getEnhancedCpcEnabled();
                            }

                            for (Setting setting : campaign.getSettings()) {
                                if (setting instanceof GeoTargetTypeSetting) {
                                    if (((GeoTargetTypeSetting) setting).getNegativeGeoTargetType() == GeoTargetTypeSettingNegativeGeoTargetType.DONT_CARE) {
                                        stat.GeoTargetNegativeType = "D";
                                    } else if (((GeoTargetTypeSetting) setting).getNegativeGeoTargetType() == GeoTargetTypeSettingNegativeGeoTargetType.LOCATION_OF_PRESENCE) {
                                        stat.GeoTargetNegativeType = "L";
                                    }

                                    if (((GeoTargetTypeSetting) setting).getPositiveGeoTargetType() == GeoTargetTypeSettingPositiveGeoTargetType.DONT_CARE) {
                                        stat.GeoTargetPositiveType = "D";
                                    } else if (((GeoTargetTypeSetting) setting).getPositiveGeoTargetType() == GeoTargetTypeSettingPositiveGeoTargetType.AREA_OF_INTEREST) {
                                        stat.GeoTargetPositiveType = "A";
                                    } else if (((GeoTargetTypeSetting) setting).getPositiveGeoTargetType() == GeoTargetTypeSettingPositiveGeoTargetType.LOCATION_OF_PRESENCE) {
                                        stat.GeoTargetPositiveType = "L";
                                    }
                                } else if (setting instanceof RealTimeBiddingSetting) {
                                    stat.KeywordMatch = ((RealTimeBiddingSetting) setting).getOptIn();
                                } else if (setting instanceof DynamicSearchAdsSetting) {
                                    stat.UsesDynamicSearchAds = true;
                                    stat.DSADomainName = ((DynamicSearchAdsSetting) setting).getDomainName();
                                    stat.DSALanguageCode = ((DynamicSearchAdsSetting) setting).getLanguageCode();
                                }
                            }
                            result.add(stat);
                        }
                    }


                    offset += PAGE_SIZE;
                    selector.getPaging().setStartIndex(offset);

                } while (offset < page.getTotalNumEntries());


            } catch (RemoteException e) {
                e.printStackTrace(System.out);
            }
        } catch (Exception e) {
            e.printStackTrace(System.out);
        }


        return result;
    }

    protected ArrayList<GA_CampaignStats> GetCampaignStatsWithRemoved(ArrayList<String> campaignsToFilterOut) {

        ArrayList<GA_CampaignStats> result = new ArrayList<GA_CampaignStats>();
        try {
            // Get the instance of service's factory
            ServiceFactory sf = ServiceFactory.getInstance();

            // Get campaign service
            CampaignServiceInterface campaignService = sf.GetCampaignService(this.GetClientId());

            int offset = 0;
            Selector selector = new Selector();

            selector.setPaging(new Paging(offset, PAGE_SIZE));

            selector.setFields(new String[]
                    {
                            "AdServingOptimizationStatus",
                            "BidCeiling",
                            "BiddingStrategyType",
                            "BidType",
                            "BudgetId",
                            "EndDate",
                            "EnhancedCpcEnabled",
                            "FrequencyCapMaxImpressions",
                            "Id",
                            "Level",
                            "Name",
                            "PricingMode",
                            "StartDate",
                            "Status",
                            "Settings",
                            "TargetContentNetwork",
                            "TargetGoogleSearch",
                            "TargetPartnerSearchNetwork",
                            "TargetSearchNetwork",
                            "TimeUnit",
                    });

            if (!campaignsToFilterOut.isEmpty()) {
                Object[] campaignsToArray = campaignsToFilterOut.toArray();
                String[] campaigns = new String[campaignsToArray.length];
                for (int i=0; i<campaignsToArray.length; i++) {
                    campaigns[i] = (String)campaignsToArray[i];
                }
                Predicate predicate = new Predicate("Id", PredicateOperator.NOT_IN, campaigns);
                Predicate[] predicates = new Predicate[]{predicate};
                selector.setPredicates(predicates);
            }

            CampaignPage page = null;

            do {

                page = campaignService.get(selector);

                if (page.getEntries() != null) {

                    for (Campaign campaign : page.getEntries()) {

                        GA_CampaignStats stat = new GA_CampaignStats();

                        if (campaign.getAdServingOptimizationStatus() == AdServingOptimizationStatus.OPTIMIZE) {
                            stat.AdServingOptimizationStatus = "O";
                        } else if (campaign.getAdServingOptimizationStatus() == AdServingOptimizationStatus.CONVERSION_OPTIMIZE) {
                            stat.AdServingOptimizationStatus = "C";
                        } else if (campaign.getAdServingOptimizationStatus() == AdServingOptimizationStatus.ROTATE) {
                            stat.AdServingOptimizationStatus = "R";
                        } else if (campaign.getAdServingOptimizationStatus() == AdServingOptimizationStatus.ROTATE_INDEFINITELY) {
                            stat.AdServingOptimizationStatus = "RI";
                        } else if (campaign.getAdServingOptimizationStatus() == AdServingOptimizationStatus.UNAVAILABLE) {
                            stat.AdServingOptimizationStatus = "U";
                        }

                        if (campaign.getBiddingStrategyConfiguration().getBiddingStrategyType() == BiddingStrategyType.BUDGET_OPTIMIZER) {
                            stat.BiddingStrategyType = "BO";
                        } else if (campaign.getBiddingStrategyConfiguration().getBiddingStrategyType() == BiddingStrategyType.CONVERSION_OPTIMIZER) {
                            stat.BiddingStrategyType = "CO";
                        } else if (campaign.getBiddingStrategyConfiguration().getBiddingStrategyType() == BiddingStrategyType.MANUAL_CPC) {
                            stat.BiddingStrategyType = "MCPC";
                        } else if (campaign.getBiddingStrategyConfiguration().getBiddingStrategyType() == BiddingStrategyType.MANUAL_CPM) {
                            stat.BiddingStrategyType = "MCPM";
                        }

                        stat.BudgetId = campaign.getBudget().getBudgetId();
                        stat.EndDate = campaign.getEndDate();
                        stat.Id = campaign.getId();
                        stat.Name = campaign.getName();
                        stat.StartDate = campaign.getStartDate();

                        if (campaign.getStatus() == CampaignStatus.ENABLED) {
                            stat.Status = "A";
                        } else if (campaign.getStatus() == CampaignStatus.REMOVED) {
                            stat.Status = "D";
                        } else if (campaign.getStatus() == CampaignStatus.PAUSED) {
                            stat.Status = "P";
                        }

                        stat.TargetContentNetwork = campaign.getNetworkSetting().getTargetContentNetwork();
                        stat.TargetGoogleSearch = campaign.getNetworkSetting().getTargetGoogleSearch();
                        stat.TargetPartnerSearchNetwork = campaign.getNetworkSetting().getTargetPartnerSearchNetwork();
                        stat.TargetSearchNetwork = campaign.getNetworkSetting().getTargetSearchNetwork();

                        if (campaign.getFrequencyCap() != null) {
                            stat.FrequencyCapMaxImpressions = campaign.getFrequencyCap().getImpressions();
                            if (campaign.getFrequencyCap().getLevel() == Level.CREATIVE) {
                                stat.Level = "C";
                            } else if (campaign.getFrequencyCap().getLevel() == Level.ADGROUP) {
                                stat.Level = "A";
                            } else if (campaign.getFrequencyCap().getLevel() == Level.CAMPAIGN) {
                                stat.Level = "CM";
                            } else if (campaign.getFrequencyCap().getLevel() == Level.UNKNOWN) {
                                stat.Level = "U";
                            }

                            if (campaign.getFrequencyCap().getTimeUnit() == TimeUnit.MINUTE) {
                                stat.TimeUnit = "M";
                            } else if (campaign.getFrequencyCap().getTimeUnit() == TimeUnit.HOUR) {
                                stat.TimeUnit = "H";
                            } else if (campaign.getFrequencyCap().getTimeUnit() == TimeUnit.DAY) {
                                stat.TimeUnit = "D";
                            } else if (campaign.getFrequencyCap().getTimeUnit() == TimeUnit.WEEK) {
                                stat.TimeUnit = "W";
                            } else if (campaign.getFrequencyCap().getTimeUnit() == TimeUnit.MONTH) {
                                stat.TimeUnit = "MN";
                            } else if (campaign.getFrequencyCap().getTimeUnit() == TimeUnit.LIFETIME) {
                                stat.TimeUnit = "L";
                            }
                        }

                        BiddingScheme bs = campaign.getBiddingStrategyConfiguration().getBiddingScheme();
                        if (bs instanceof BudgetOptimizerBiddingScheme) {
                            if (((BudgetOptimizerBiddingScheme)campaign.getBiddingStrategyConfiguration().getBiddingScheme()).getBidCeiling() != null) {
                                stat.BidCeiling = (double)((BudgetOptimizerBiddingScheme)campaign.getBiddingStrategyConfiguration().getBiddingScheme()).getBidCeiling().getMicroAmount() / (double)1000000;
                            }
                            stat.EnhancedCpcEnabled = ((BudgetOptimizerBiddingScheme)campaign.getBiddingStrategyConfiguration().getBiddingScheme()).getEnhancedCpcEnabled();
                        } else if (bs instanceof ConversionOptimizerBiddingScheme) {
                            if (((ConversionOptimizerBiddingScheme)campaign.getBiddingStrategyConfiguration().getBiddingScheme()).getBidType() == ConversionOptimizerBiddingSchemeBidType.TARGET_CPA) {
                                stat.BidType = "T";
                            }

                            if (((ConversionOptimizerBiddingScheme)campaign.getBiddingStrategyConfiguration().getBiddingScheme()).getPricingMode() == ConversionOptimizerBiddingSchemePricingMode.CLICKS) {
                                stat.PricingMode = "C";
                            } else if (((ConversionOptimizerBiddingScheme)campaign.getBiddingStrategyConfiguration().getBiddingScheme()).getPricingMode() == ConversionOptimizerBiddingSchemePricingMode.CONVERSIONS) {
                                stat.PricingMode = "CN";
                            }
                        } else if (bs instanceof ManualCpcBiddingScheme) {
                            stat.EnhancedCpcEnabled = ((ManualCpcBiddingScheme)campaign.getBiddingStrategyConfiguration().getBiddingScheme()).getEnhancedCpcEnabled();
                        }

                        for (Setting setting : campaign.getSettings()) {
                            if (setting instanceof GeoTargetTypeSetting) {
                                if (((GeoTargetTypeSetting)setting).getNegativeGeoTargetType() == GeoTargetTypeSettingNegativeGeoTargetType.DONT_CARE) {
                                    stat.GeoTargetNegativeType = "D";
                                } else if (((GeoTargetTypeSetting)setting).getNegativeGeoTargetType() == GeoTargetTypeSettingNegativeGeoTargetType.LOCATION_OF_PRESENCE) {
                                    stat.GeoTargetNegativeType = "L";
                                }

                                if (((GeoTargetTypeSetting)setting).getPositiveGeoTargetType() == GeoTargetTypeSettingPositiveGeoTargetType.DONT_CARE) {
                                    stat.GeoTargetPositiveType = "D";
                                } else if (((GeoTargetTypeSetting)setting).getPositiveGeoTargetType() == GeoTargetTypeSettingPositiveGeoTargetType.AREA_OF_INTEREST) {
                                    stat.GeoTargetPositiveType = "A";
                                } else if (((GeoTargetTypeSetting)setting).getPositiveGeoTargetType() == GeoTargetTypeSettingPositiveGeoTargetType.LOCATION_OF_PRESENCE) {
                                    stat.GeoTargetPositiveType = "L";
                                }
                            }else if (setting instanceof RealTimeBiddingSetting) {
                                stat.KeywordMatch = ((RealTimeBiddingSetting)setting).getOptIn();
                            } else if (setting instanceof DynamicSearchAdsSetting) {
                                stat.UsesDynamicSearchAds = true;
                                stat.DSADomainName = ((DynamicSearchAdsSetting) setting).getDomainName();
                                stat.DSALanguageCode = ((DynamicSearchAdsSetting) setting).getLanguageCode();
                            }
                        }
                        result.add(stat);
                    }
                }


                offset += PAGE_SIZE;
                selector.getPaging().setStartIndex(offset);

            } while (offset < page.getTotalNumEntries());


        } catch (Exception e) {
            e.printStackTrace(System.out);
        }


        return result;
    }


    public ArrayList<GA_CampaignStats> GetCampaignStats(String campaignId) {

        ArrayList<GA_CampaignStats> result = new ArrayList<GA_CampaignStats>();

        // Get the instance of service's factory
        ServiceFactory sf = ServiceFactory.getInstance();

        try {
            // Get campaign service
            CampaignServiceInterface campaignService = sf.GetCampaignService(this.GetClientId());

            int offset = 0;
            Selector selector = new Selector();

            selector.setPaging(new Paging(offset, PAGE_SIZE));

            selector.setFields(new String[]
                    {
                            "AdServingOptimizationStatus",
                            "BidCeiling",
                            "BiddingStrategyType",
                            "BiddingStrategyId",
                            "BiddingStrategyName",
                            "BidType",
                            "BudgetId",
                            "EndDate",
                            "EnhancedCpcEnabled",
                            "FrequencyCapMaxImpressions",
                            "AdvertisingChannelType",
                            "Id",
                            "Level",
                            "Name",
                            "PricingMode",
                            "StartDate",
                            "Status",
                            "Settings",
                            "TargetContentNetwork",
                            "TargetGoogleSearch",
                            "TargetPartnerSearchNetwork",
                            "TargetSearchNetwork",
                            "TimeUnit"
                    });

            Predicate predicate = new Predicate("Status", PredicateOperator.NOT_EQUALS, new String[]{"REMOVED"});
            Predicate campaignIdPredicate = new Predicate("Id", PredicateOperator.EQUALS, new String[]{campaignId});
            Predicate[] predicates = new Predicate[]{predicate, campaignIdPredicate};
            selector.setPredicates(predicates);


            CampaignPage page = null;

            try {

                do {

                    page = campaignService.get(selector);

                    if (page.getEntries() != null) {

                        for (Campaign campaign : page.getEntries()) {

                            GA_CampaignStats stat = new GA_CampaignStats();

                            if (campaign.getAdServingOptimizationStatus() == AdServingOptimizationStatus.OPTIMIZE) {
                                stat.AdServingOptimizationStatus = "O";
                            } else if (campaign.getAdServingOptimizationStatus() == AdServingOptimizationStatus.CONVERSION_OPTIMIZE) {
                                stat.AdServingOptimizationStatus = "C";
                            } else if (campaign.getAdServingOptimizationStatus() == AdServingOptimizationStatus.ROTATE) {
                                stat.AdServingOptimizationStatus = "R";
                            } else if (campaign.getAdServingOptimizationStatus() == AdServingOptimizationStatus.ROTATE_INDEFINITELY) {
                                stat.AdServingOptimizationStatus = "RI";
                            } else if (campaign.getAdServingOptimizationStatus() == AdServingOptimizationStatus.UNAVAILABLE) {
                                stat.AdServingOptimizationStatus = "U";
                            }

                            if (campaign.getBiddingStrategyConfiguration().getBiddingStrategyType() == BiddingStrategyType.BUDGET_OPTIMIZER) {
                                stat.BiddingStrategyType = "BO";
                            } else if (campaign.getBiddingStrategyConfiguration().getBiddingStrategyType() == BiddingStrategyType.CONVERSION_OPTIMIZER) {
                                stat.BiddingStrategyType = "CO";
                            } else if (campaign.getBiddingStrategyConfiguration().getBiddingStrategyType() == BiddingStrategyType.MANUAL_CPC) {
                                stat.BiddingStrategyType = "MCPC";
                            } else if (campaign.getBiddingStrategyConfiguration().getBiddingStrategyType() == BiddingStrategyType.MANUAL_CPM) {
                                stat.BiddingStrategyType = "MCPM";
                            }

                            stat.BudgetId = campaign.getBudget().getBudgetId();
                            stat.EndDate = campaign.getEndDate();
                            stat.Id = campaign.getId();
                            stat.Name = campaign.getName();
                            stat.StartDate = campaign.getStartDate();
                            stat.AdvertisingChannelType = campaign.getAdvertisingChannelType().getValue();

                            if (campaign.getStatus() == CampaignStatus.ENABLED) {
                                stat.Status = "A";
                            } else if (campaign.getStatus() == CampaignStatus.REMOVED) {
                                stat.Status = "D";
                            } else if (campaign.getStatus() == CampaignStatus.PAUSED) {
                                stat.Status = "P";
                            }

                            stat.TargetContentNetwork = campaign.getNetworkSetting().getTargetContentNetwork();
                            stat.TargetGoogleSearch = campaign.getNetworkSetting().getTargetGoogleSearch();
                            stat.TargetPartnerSearchNetwork = campaign.getNetworkSetting().getTargetPartnerSearchNetwork();
                            stat.TargetSearchNetwork = campaign.getNetworkSetting().getTargetSearchNetwork();

                            if (campaign.getFrequencyCap() != null) {
                                stat.FrequencyCapMaxImpressions = campaign.getFrequencyCap().getImpressions();
                                if (campaign.getFrequencyCap().getLevel() == Level.CREATIVE) {
                                    stat.Level = "C";
                                } else if (campaign.getFrequencyCap().getLevel() == Level.ADGROUP) {
                                    stat.Level = "A";
                                } else if (campaign.getFrequencyCap().getLevel() == Level.CAMPAIGN) {
                                    stat.Level = "CM";
                                } else if (campaign.getFrequencyCap().getLevel() == Level.UNKNOWN) {
                                    stat.Level = "U";
                                }

                                if (campaign.getFrequencyCap().getTimeUnit() == TimeUnit.MINUTE) {
                                    stat.TimeUnit = "M";
                                } else if (campaign.getFrequencyCap().getTimeUnit() == TimeUnit.HOUR) {
                                    stat.TimeUnit = "H";
                                } else if (campaign.getFrequencyCap().getTimeUnit() == TimeUnit.DAY) {
                                    stat.TimeUnit = "D";
                                } else if (campaign.getFrequencyCap().getTimeUnit() == TimeUnit.WEEK) {
                                    stat.TimeUnit = "W";
                                } else if (campaign.getFrequencyCap().getTimeUnit() == TimeUnit.MONTH) {
                                    stat.TimeUnit = "MN";
                                } else if (campaign.getFrequencyCap().getTimeUnit() == TimeUnit.LIFETIME) {
                                    stat.TimeUnit = "L";
                                }
                            }

                            BiddingScheme bs = campaign.getBiddingStrategyConfiguration().getBiddingScheme();
                            if (bs instanceof BudgetOptimizerBiddingScheme) {
                                if (((BudgetOptimizerBiddingScheme) campaign.getBiddingStrategyConfiguration().getBiddingScheme()).getBidCeiling() != null) {
                                    stat.BidCeiling = (double) ((BudgetOptimizerBiddingScheme) campaign.getBiddingStrategyConfiguration().getBiddingScheme()).getBidCeiling().getMicroAmount() / (double) 1000000;
                                }
                                stat.EnhancedCpcEnabled = ((BudgetOptimizerBiddingScheme) campaign.getBiddingStrategyConfiguration().getBiddingScheme()).getEnhancedCpcEnabled();
                            } else if (bs instanceof ConversionOptimizerBiddingScheme) {
                                if (((ConversionOptimizerBiddingScheme) campaign.getBiddingStrategyConfiguration().getBiddingScheme()).getBidType() == ConversionOptimizerBiddingSchemeBidType.TARGET_CPA) {
                                    stat.BidType = "T";
                                }
                                if (((ConversionOptimizerBiddingScheme) campaign.getBiddingStrategyConfiguration().getBiddingScheme()).getPricingMode() == ConversionOptimizerBiddingSchemePricingMode.CLICKS) {
                                    stat.PricingMode = "C";
                                } else if (((ConversionOptimizerBiddingScheme) campaign.getBiddingStrategyConfiguration().getBiddingScheme()).getPricingMode() == ConversionOptimizerBiddingSchemePricingMode.CONVERSIONS) {
                                    stat.PricingMode = "CN";
                                }
                            } else if (bs instanceof ManualCpcBiddingScheme) {
                                stat.EnhancedCpcEnabled = ((ManualCpcBiddingScheme) campaign.getBiddingStrategyConfiguration().getBiddingScheme()).getEnhancedCpcEnabled();
                            }

                            BiddingStrategyConfiguration bsc = campaign.getBiddingStrategyConfiguration();

                            stat.BiddingStrategyId = bsc.getBiddingStrategyId();
                            stat.BiddingStrategyName = bsc.getBiddingStrategyName();
                            stat.BiddingStrategyType = bsc.getBiddingStrategyType().getValue();

                            for (Setting setting : campaign.getSettings()) {
                                if (setting instanceof GeoTargetTypeSetting) {
                                    if (((GeoTargetTypeSetting) setting).getNegativeGeoTargetType() == GeoTargetTypeSettingNegativeGeoTargetType.DONT_CARE) {
                                        stat.GeoTargetNegativeType = "D";
                                    } else if (((GeoTargetTypeSetting) setting).getNegativeGeoTargetType() == GeoTargetTypeSettingNegativeGeoTargetType.LOCATION_OF_PRESENCE) {
                                        stat.GeoTargetNegativeType = "L";
                                    }

                                    if (((GeoTargetTypeSetting) setting).getPositiveGeoTargetType() == GeoTargetTypeSettingPositiveGeoTargetType.DONT_CARE) {
                                        stat.GeoTargetPositiveType = "D";
                                    } else if (((GeoTargetTypeSetting) setting).getPositiveGeoTargetType() == GeoTargetTypeSettingPositiveGeoTargetType.AREA_OF_INTEREST) {
                                        stat.GeoTargetPositiveType = "A";
                                    } else if (((GeoTargetTypeSetting) setting).getPositiveGeoTargetType() == GeoTargetTypeSettingPositiveGeoTargetType.LOCATION_OF_PRESENCE) {
                                        stat.GeoTargetPositiveType = "L";
                                    }
                                } else if (setting instanceof RealTimeBiddingSetting) {
                                    stat.KeywordMatch = ((RealTimeBiddingSetting) setting).getOptIn();
                                } else if (setting instanceof DynamicSearchAdsSetting) {
                                    stat.UsesDynamicSearchAds = true;
                                    stat.DSADomainName = ((DynamicSearchAdsSetting) setting).getDomainName();
                                    stat.DSALanguageCode = ((DynamicSearchAdsSetting) setting).getLanguageCode();
                                }
                            }
                            result.add(stat);
                        }
                    }


                    offset += PAGE_SIZE;
                    selector.getPaging().setStartIndex(offset);

                } while (offset < page.getTotalNumEntries());


            } catch (RemoteException e) {
                e.printStackTrace(System.out);
            }
        } catch (Exception e) {
            e.printStackTrace(System.out);
        }
        return result;
    }

    protected ArrayList<BudgetReport> GetBudgetStats() {
        ArrayList<BudgetReport> result = new ArrayList<BudgetReport>();

        // Get the instance of service's factory
        ServiceFactory sf = ServiceFactory.getInstance();

        try {
            // Get budget service
            BudgetServiceInterface budgetService = sf.GetBudgetService(this.GetClientId());

            int offset = 0;
            Selector selector = new Selector();

            selector.setPaging(new Paging(offset, PAGE_SIZE));

            selector.setFields(new String[]{
                    "Amount",
                    "BudgetId",
                    "BudgetName",
                    "BudgetStatus",
                    "DeliveryMethod",
                    "IsBudgetExplicitlyShared",
                    "Period"
            });

            Predicate predicate = new Predicate("BudgetStatus", PredicateOperator.NOT_EQUALS, new String[]{"REMOVED"});
            Predicate[] predicates = new Predicate[]{predicate};
            selector.setPredicates(predicates);

            BudgetPage page = null;

            try {
                do {
                    page = budgetService.get(selector);
                    if (page.getEntries() != null) {
                        for (Budget budget : page.getEntries()) {
                            BudgetReport budgetReport = new BudgetReport();

                            budgetReport.Amount = (double) budget.getAmount().getMicroAmount() / (double) 1000000;
                            budgetReport.BudgetId = budget.getBudgetId();
                            budgetReport.BudgetName = budget.getName();
                            budgetReport.IsBudgetExplicitlyShared = budget.getIsExplicitlyShared();

                            if (budget.getStatus() == BudgetBudgetStatus.ENABLED) {
                                budgetReport.BudgetStatus = "A";
                            } else if (budget.getStatus() == BudgetBudgetStatus.REMOVED) {
                                budgetReport.BudgetStatus = "D";
                            } else if (budget.getStatus() == BudgetBudgetStatus.UNKNOWN) {
                                budgetReport.BudgetStatus = "U";
                            }

                            if (budget.getDeliveryMethod() == BudgetBudgetDeliveryMethod.ACCELERATED) {
                                budgetReport.DeliveryMethod = "A";
                            } else if (budget.getDeliveryMethod() == BudgetBudgetDeliveryMethod.STANDARD) {
                                budgetReport.DeliveryMethod = "S";
                            }

                            if (budget.getPeriod() == BudgetBudgetPeriod.DAILY) {
                                budgetReport.Period = "D";
                            }

                            result.add(budgetReport);
                        }
                    }


                    offset += PAGE_SIZE;
                    selector.getPaging().setStartIndex(offset);

                } while (offset < page.getTotalNumEntries());


            } catch (RemoteException e) {
                e.printStackTrace(System.out);
            }
        } catch (Exception e) {
            e.printStackTrace(System.out);
        }
        return result;
    }

    protected ArrayList<Long> GetAllCampaignId(){

        ArrayList<Long> result = new ArrayList<Long>();

        // Get the instance of service's factory
        ServiceFactory sf = ServiceFactory.getInstance();

        try {
            // Get campaign service
            CampaignServiceInterface campaignService = sf.GetCampaignService(this.GetClientId());

            int offset = 0;
            Selector selector = new Selector();

            selector.setPaging(new Paging(offset, PAGE_SIZE));

            selector.setFields(new String[]{"Id", "Status"});

            // Create predicates.
            Predicate campaignStatus =
                    new Predicate("Status", PredicateOperator.IN, new String[]{"ENABLED", "PAUSED"});
            selector.setPredicates(new Predicate[]{campaignStatus});


            CampaignPage page = null;

            try {

                do {

                    page = campaignService.get(selector);

                    if (page.getEntries() != null) {

                        for (Campaign campaign : page.getEntries()) {

                            result.add(campaign.getId());

                        }
                    }
                    offset += PAGE_SIZE;
                    selector.getPaging().setStartIndex(offset);

                } while (offset < page.getTotalNumEntries());
            } catch (RemoteException e) {
                e.printStackTrace(System.out);
            }
        } catch (Exception e) {
            e.printStackTrace(System.out);
        }
        return result;
    }


    private Document loadXMLFromString(String xml) throws Exception {
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        DocumentBuilder builder = factory.newDocumentBuilder();
        factory.setNamespaceAware(true); // never forget this!
        InputSource is = new InputSource(new StringReader(xml));
        return builder.parse(is);
    }

}

